Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6: (37 commits) [XFS] Fix lockdep annotations for xfs_lock_inodes [LIB]: export radix_tree_preload() [XFS] Fix XFS_IOC_FSBULKSTAT{,_SINGLE} & XFS_IOC_FSINUMBERS in compat mode [XFS] Compat ioctl handler for handle operations [XFS] Compat ioctl handler for XFS_IOC_FSGEOMETRY_V1. [XFS] Clean up function name handling in tracing code [XFS] Quota inode has no parent. [XFS] Concurrent Multi-File Data Streams [XFS] Use uninitialized_var macro to stop warning about rtx [XFS] XFS should not be looking at filp reference counts [XFS] Use is_power_of_2 instead of open coding checks [XFS] Reduce shouting by removing unnecessary macros from dir2 code. [XFS] Simplify XFS min/max macros. [XFS] Kill off xfs_count_bits [XFS] Cancel transactions on xfs_itruncate_start error. [XFS] Use do_div() on 64 bit types. [XFS] Fix remount,readonly path to flush everything correctly. [XFS] Cleanup inode extent size hint extraction [XFS] Prevent ENOSPC from aborting transactions that need to succeed [XFS] Prevent deadlock when flushing inodes on unmount ...
This commit is contained in:
Коммит
2d896c780d
|
@ -64,6 +64,7 @@ xfs-y += xfs_alloc.o \
|
|||
xfs_dir2_sf.o \
|
||||
xfs_error.o \
|
||||
xfs_extfree_item.o \
|
||||
xfs_filestream.o \
|
||||
xfs_fsops.o \
|
||||
xfs_ialloc.o \
|
||||
xfs_ialloc_btree.o \
|
||||
|
@ -77,6 +78,7 @@ xfs-y += xfs_alloc.o \
|
|||
xfs_log.o \
|
||||
xfs_log_recover.o \
|
||||
xfs_mount.o \
|
||||
xfs_mru_cache.o \
|
||||
xfs_rename.o \
|
||||
xfs_trans.o \
|
||||
xfs_trans_ail.o \
|
||||
|
|
|
@ -100,25 +100,6 @@ kmem_zone_destroy(kmem_zone_t *zone)
|
|||
extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
|
||||
extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
|
||||
|
||||
/*
|
||||
* Low memory cache shrinkers
|
||||
*/
|
||||
|
||||
typedef struct shrinker *kmem_shaker_t;
|
||||
typedef int (*kmem_shake_func_t)(int, gfp_t);
|
||||
|
||||
static inline kmem_shaker_t
|
||||
kmem_shake_register(kmem_shake_func_t sfunc)
|
||||
{
|
||||
return set_shrinker(DEFAULT_SEEKS, sfunc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
kmem_shake_deregister(kmem_shaker_t shrinker)
|
||||
{
|
||||
remove_shrinker(shrinker);
|
||||
}
|
||||
|
||||
static inline int
|
||||
kmem_shake_allow(gfp_t gfp_mask)
|
||||
{
|
||||
|
|
|
@ -108,14 +108,19 @@ xfs_page_trace(
|
|||
|
||||
/*
|
||||
* Schedule IO completion handling on a xfsdatad if this was
|
||||
* the final hold on this ioend.
|
||||
* the final hold on this ioend. If we are asked to wait,
|
||||
* flush the workqueue.
|
||||
*/
|
||||
STATIC void
|
||||
xfs_finish_ioend(
|
||||
xfs_ioend_t *ioend)
|
||||
xfs_ioend_t *ioend,
|
||||
int wait)
|
||||
{
|
||||
if (atomic_dec_and_test(&ioend->io_remaining))
|
||||
if (atomic_dec_and_test(&ioend->io_remaining)) {
|
||||
queue_work(xfsdatad_workqueue, &ioend->io_work);
|
||||
if (wait)
|
||||
flush_workqueue(xfsdatad_workqueue);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -156,6 +161,8 @@ xfs_setfilesize(
|
|||
xfs_fsize_t bsize;
|
||||
|
||||
ip = xfs_vtoi(ioend->io_vnode);
|
||||
if (!ip)
|
||||
return;
|
||||
|
||||
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
|
||||
ASSERT(ioend->io_type != IOMAP_READ);
|
||||
|
@ -334,7 +341,7 @@ xfs_end_bio(
|
|||
bio->bi_end_io = NULL;
|
||||
bio_put(bio);
|
||||
|
||||
xfs_finish_ioend(ioend);
|
||||
xfs_finish_ioend(ioend, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -470,7 +477,7 @@ xfs_submit_ioend(
|
|||
}
|
||||
if (bio)
|
||||
xfs_submit_ioend_bio(ioend, bio);
|
||||
xfs_finish_ioend(ioend);
|
||||
xfs_finish_ioend(ioend, 0);
|
||||
} while ((ioend = next) != NULL);
|
||||
}
|
||||
|
||||
|
@ -1003,6 +1010,8 @@ xfs_page_state_convert(
|
|||
if (buffer_unwritten(bh) || buffer_delay(bh) ||
|
||||
((buffer_uptodate(bh) || PageUptodate(page)) &&
|
||||
!buffer_mapped(bh) && (unmapped || startio))) {
|
||||
int new_ioend = 0;
|
||||
|
||||
/*
|
||||
* Make sure we don't use a read-only iomap
|
||||
*/
|
||||
|
@ -1021,6 +1030,15 @@ xfs_page_state_convert(
|
|||
}
|
||||
|
||||
if (!iomap_valid) {
|
||||
/*
|
||||
* if we didn't have a valid mapping then we
|
||||
* need to ensure that we put the new mapping
|
||||
* in a new ioend structure. This needs to be
|
||||
* done to ensure that the ioends correctly
|
||||
* reflect the block mappings at io completion
|
||||
* for unwritten extent conversion.
|
||||
*/
|
||||
new_ioend = 1;
|
||||
if (type == IOMAP_NEW) {
|
||||
size = xfs_probe_cluster(inode,
|
||||
page, bh, head, 0);
|
||||
|
@ -1040,7 +1058,7 @@ xfs_page_state_convert(
|
|||
if (startio) {
|
||||
xfs_add_to_ioend(inode, bh, offset,
|
||||
type, &ioend,
|
||||
!iomap_valid);
|
||||
new_ioend);
|
||||
} else {
|
||||
set_buffer_dirty(bh);
|
||||
unlock_buffer(bh);
|
||||
|
@ -1416,6 +1434,13 @@ xfs_end_io_direct(
|
|||
* This is not necessary for synchronous direct I/O, but we do
|
||||
* it anyway to keep the code uniform and simpler.
|
||||
*
|
||||
* Well, if only it were that simple. Because synchronous direct I/O
|
||||
* requires extent conversion to occur *before* we return to userspace,
|
||||
* we have to wait for extent conversion to complete. Look at the
|
||||
* iocb that has been passed to us to determine if this is AIO or
|
||||
* not. If it is synchronous, tell xfs_finish_ioend() to kick the
|
||||
* workqueue and wait for it to complete.
|
||||
*
|
||||
* The core direct I/O code might be changed to always call the
|
||||
* completion handler in the future, in which case all this can
|
||||
* go away.
|
||||
|
@ -1423,9 +1448,9 @@ xfs_end_io_direct(
|
|||
ioend->io_offset = offset;
|
||||
ioend->io_size = size;
|
||||
if (ioend->io_type == IOMAP_READ) {
|
||||
xfs_finish_ioend(ioend);
|
||||
xfs_finish_ioend(ioend, 0);
|
||||
} else if (private && size > 0) {
|
||||
xfs_finish_ioend(ioend);
|
||||
xfs_finish_ioend(ioend, is_sync_kiocb(iocb));
|
||||
} else {
|
||||
/*
|
||||
* A direct I/O write ioend starts it's life in unwritten
|
||||
|
@ -1434,7 +1459,7 @@ xfs_end_io_direct(
|
|||
* handler.
|
||||
*/
|
||||
INIT_WORK(&ioend->io_work, xfs_end_bio_written);
|
||||
xfs_finish_ioend(ioend);
|
||||
xfs_finish_ioend(ioend, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <linux/freezer.h>
|
||||
|
||||
static kmem_zone_t *xfs_buf_zone;
|
||||
static kmem_shaker_t xfs_buf_shake;
|
||||
static struct shrinker *xfs_buf_shake;
|
||||
STATIC int xfsbufd(void *);
|
||||
STATIC int xfsbufd_wakeup(int, gfp_t);
|
||||
STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
|
||||
|
@ -314,7 +314,7 @@ xfs_buf_free(
|
|||
|
||||
ASSERT(list_empty(&bp->b_hash_list));
|
||||
|
||||
if (bp->b_flags & _XBF_PAGE_CACHE) {
|
||||
if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
|
||||
uint i;
|
||||
|
||||
if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
|
||||
|
@ -323,18 +323,11 @@ xfs_buf_free(
|
|||
for (i = 0; i < bp->b_page_count; i++) {
|
||||
struct page *page = bp->b_pages[i];
|
||||
|
||||
ASSERT(!PagePrivate(page));
|
||||
if (bp->b_flags & _XBF_PAGE_CACHE)
|
||||
ASSERT(!PagePrivate(page));
|
||||
page_cache_release(page);
|
||||
}
|
||||
_xfs_buf_free_pages(bp);
|
||||
} else if (bp->b_flags & _XBF_KMEM_ALLOC) {
|
||||
/*
|
||||
* XXX(hch): bp->b_count_desired might be incorrect (see
|
||||
* xfs_buf_associate_memory for details), but fortunately
|
||||
* the Linux version of kmem_free ignores the len argument..
|
||||
*/
|
||||
kmem_free(bp->b_addr, bp->b_count_desired);
|
||||
_xfs_buf_free_pages(bp);
|
||||
}
|
||||
|
||||
xfs_buf_deallocate(bp);
|
||||
|
@ -764,43 +757,44 @@ xfs_buf_get_noaddr(
|
|||
size_t len,
|
||||
xfs_buftarg_t *target)
|
||||
{
|
||||
size_t malloc_len = len;
|
||||
unsigned long page_count = PAGE_ALIGN(len) >> PAGE_SHIFT;
|
||||
int error, i;
|
||||
xfs_buf_t *bp;
|
||||
void *data;
|
||||
int error;
|
||||
|
||||
bp = xfs_buf_allocate(0);
|
||||
if (unlikely(bp == NULL))
|
||||
goto fail;
|
||||
_xfs_buf_initialize(bp, target, 0, len, 0);
|
||||
|
||||
try_again:
|
||||
data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL | KM_LARGE);
|
||||
if (unlikely(data == NULL))
|
||||
error = _xfs_buf_get_pages(bp, page_count, 0);
|
||||
if (error)
|
||||
goto fail_free_buf;
|
||||
|
||||
/* check whether alignment matches.. */
|
||||
if ((__psunsigned_t)data !=
|
||||
((__psunsigned_t)data & ~target->bt_smask)) {
|
||||
/* .. else double the size and try again */
|
||||
kmem_free(data, malloc_len);
|
||||
malloc_len <<= 1;
|
||||
goto try_again;
|
||||
for (i = 0; i < page_count; i++) {
|
||||
bp->b_pages[i] = alloc_page(GFP_KERNEL);
|
||||
if (!bp->b_pages[i])
|
||||
goto fail_free_mem;
|
||||
}
|
||||
bp->b_flags |= _XBF_PAGES;
|
||||
|
||||
error = xfs_buf_associate_memory(bp, data, len);
|
||||
if (error)
|
||||
error = _xfs_buf_map_pages(bp, XBF_MAPPED);
|
||||
if (unlikely(error)) {
|
||||
printk(KERN_WARNING "%s: failed to map pages\n",
|
||||
__FUNCTION__);
|
||||
goto fail_free_mem;
|
||||
bp->b_flags |= _XBF_KMEM_ALLOC;
|
||||
}
|
||||
|
||||
xfs_buf_unlock(bp);
|
||||
|
||||
XB_TRACE(bp, "no_daddr", data);
|
||||
XB_TRACE(bp, "no_daddr", len);
|
||||
return bp;
|
||||
|
||||
fail_free_mem:
|
||||
kmem_free(data, malloc_len);
|
||||
while (--i >= 0)
|
||||
__free_page(bp->b_pages[i]);
|
||||
_xfs_buf_free_pages(bp);
|
||||
fail_free_buf:
|
||||
xfs_buf_free(bp);
|
||||
xfs_buf_deallocate(bp);
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1453,6 +1447,7 @@ xfs_free_buftarg(
|
|||
int external)
|
||||
{
|
||||
xfs_flush_buftarg(btp, 1);
|
||||
xfs_blkdev_issue_flush(btp);
|
||||
if (external)
|
||||
xfs_blkdev_put(btp->bt_bdev);
|
||||
xfs_free_bufhash(btp);
|
||||
|
@ -1837,7 +1832,7 @@ xfs_buf_init(void)
|
|||
if (!xfsdatad_workqueue)
|
||||
goto out_destroy_xfslogd_workqueue;
|
||||
|
||||
xfs_buf_shake = kmem_shake_register(xfsbufd_wakeup);
|
||||
xfs_buf_shake = set_shrinker(DEFAULT_SEEKS, xfsbufd_wakeup);
|
||||
if (!xfs_buf_shake)
|
||||
goto out_destroy_xfsdatad_workqueue;
|
||||
|
||||
|
@ -1859,7 +1854,7 @@ xfs_buf_init(void)
|
|||
void
|
||||
xfs_buf_terminate(void)
|
||||
{
|
||||
kmem_shake_deregister(xfs_buf_shake);
|
||||
remove_shrinker(xfs_buf_shake);
|
||||
destroy_workqueue(xfsdatad_workqueue);
|
||||
destroy_workqueue(xfslogd_workqueue);
|
||||
kmem_zone_destroy(xfs_buf_zone);
|
||||
|
|
|
@ -63,7 +63,7 @@ typedef enum {
|
|||
|
||||
/* flags used only internally */
|
||||
_XBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */
|
||||
_XBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc() */
|
||||
_XBF_PAGES = (1 << 18), /* backed by refcounted pages */
|
||||
_XBF_RUN_QUEUES = (1 << 19),/* run block device task queue */
|
||||
_XBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */
|
||||
} xfs_buf_flags_t;
|
||||
|
|
|
@ -183,15 +183,6 @@ xfs_file_open(
|
|||
return -bhv_vop_open(vn_from_inode(inode), NULL);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_file_close(
|
||||
struct file *filp,
|
||||
fl_owner_t id)
|
||||
{
|
||||
return -bhv_vop_close(vn_from_inode(filp->f_path.dentry->d_inode), 0,
|
||||
file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_file_release(
|
||||
struct inode *inode,
|
||||
|
@ -436,7 +427,6 @@ const struct file_operations xfs_file_operations = {
|
|||
#endif
|
||||
.mmap = xfs_file_mmap,
|
||||
.open = xfs_file_open,
|
||||
.flush = xfs_file_close,
|
||||
.release = xfs_file_release,
|
||||
.fsync = xfs_file_fsync,
|
||||
#ifdef HAVE_FOP_OPEN_EXEC
|
||||
|
@ -458,7 +448,6 @@ const struct file_operations xfs_invis_file_operations = {
|
|||
#endif
|
||||
.mmap = xfs_file_mmap,
|
||||
.open = xfs_file_open,
|
||||
.flush = xfs_file_close,
|
||||
.release = xfs_file_release,
|
||||
.fsync = xfs_file_fsync,
|
||||
};
|
||||
|
|
|
@ -46,6 +46,7 @@ xfs_param_t xfs_params = {
|
|||
.inherit_nosym = { 0, 0, 1 },
|
||||
.rotorstep = { 1, 1, 255 },
|
||||
.inherit_nodfrg = { 0, 1, 1 },
|
||||
.fstrm_timer = { 1, 50, 3600*100},
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1019,7 +1019,7 @@ xfs_ioc_bulkstat(
|
|||
|
||||
if (cmd == XFS_IOC_FSINUMBERS)
|
||||
error = xfs_inumbers(mp, &inlast, &count,
|
||||
bulkreq.ubuffer);
|
||||
bulkreq.ubuffer, xfs_inumbers_fmt);
|
||||
else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
|
||||
error = xfs_bulkstat_single(mp, &inlast,
|
||||
bulkreq.ubuffer, &done);
|
||||
|
|
|
@ -23,10 +23,25 @@
|
|||
#include <linux/fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "xfs.h"
|
||||
#include "xfs_types.h"
|
||||
#include "xfs_fs.h"
|
||||
#include "xfs_bit.h"
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_inum.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_sb.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "xfs_dir2.h"
|
||||
#include "xfs_dmapi.h"
|
||||
#include "xfs_mount.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_attr_sf.h"
|
||||
#include "xfs_dir2_sf.h"
|
||||
#include "xfs_vfs.h"
|
||||
#include "xfs_vnode.h"
|
||||
#include "xfs_dinode.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_itable.h"
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_dfrag.h"
|
||||
|
||||
#define _NATIVE_IOC(cmd, type) \
|
||||
|
@ -34,6 +49,7 @@
|
|||
|
||||
#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
|
||||
#define BROKEN_X86_ALIGNMENT
|
||||
#define _PACKED __attribute__((packed))
|
||||
/* on ia32 l_start is on a 32-bit boundary */
|
||||
typedef struct xfs_flock64_32 {
|
||||
__s16 l_type;
|
||||
|
@ -75,35 +91,276 @@ xfs_ioctl32_flock(
|
|||
return (unsigned long)p;
|
||||
}
|
||||
|
||||
typedef struct compat_xfs_fsop_geom_v1 {
|
||||
__u32 blocksize; /* filesystem (data) block size */
|
||||
__u32 rtextsize; /* realtime extent size */
|
||||
__u32 agblocks; /* fsblocks in an AG */
|
||||
__u32 agcount; /* number of allocation groups */
|
||||
__u32 logblocks; /* fsblocks in the log */
|
||||
__u32 sectsize; /* (data) sector size, bytes */
|
||||
__u32 inodesize; /* inode size in bytes */
|
||||
__u32 imaxpct; /* max allowed inode space(%) */
|
||||
__u64 datablocks; /* fsblocks in data subvolume */
|
||||
__u64 rtblocks; /* fsblocks in realtime subvol */
|
||||
__u64 rtextents; /* rt extents in realtime subvol*/
|
||||
__u64 logstart; /* starting fsblock of the log */
|
||||
unsigned char uuid[16]; /* unique id of the filesystem */
|
||||
__u32 sunit; /* stripe unit, fsblocks */
|
||||
__u32 swidth; /* stripe width, fsblocks */
|
||||
__s32 version; /* structure version */
|
||||
__u32 flags; /* superblock version flags */
|
||||
__u32 logsectsize; /* log sector size, bytes */
|
||||
__u32 rtsectsize; /* realtime sector size, bytes */
|
||||
__u32 dirblocksize; /* directory block size, bytes */
|
||||
} __attribute__((packed)) compat_xfs_fsop_geom_v1_t;
|
||||
|
||||
#define XFS_IOC_FSGEOMETRY_V1_32 \
|
||||
_IOR ('X', 100, struct compat_xfs_fsop_geom_v1)
|
||||
|
||||
STATIC unsigned long xfs_ioctl32_geom_v1(unsigned long arg)
|
||||
{
|
||||
compat_xfs_fsop_geom_v1_t __user *p32 = (void __user *)arg;
|
||||
xfs_fsop_geom_v1_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
|
||||
if (copy_in_user(p, p32, sizeof(*p32)))
|
||||
return -EFAULT;
|
||||
return (unsigned long)p;
|
||||
}
|
||||
|
||||
typedef struct compat_xfs_inogrp {
|
||||
__u64 xi_startino; /* starting inode number */
|
||||
__s32 xi_alloccount; /* # bits set in allocmask */
|
||||
__u64 xi_allocmask; /* mask of allocated inodes */
|
||||
} __attribute__((packed)) compat_xfs_inogrp_t;
|
||||
|
||||
STATIC int xfs_inumbers_fmt_compat(
|
||||
void __user *ubuffer,
|
||||
const xfs_inogrp_t *buffer,
|
||||
long count,
|
||||
long *written)
|
||||
{
|
||||
compat_xfs_inogrp_t *p32 = ubuffer;
|
||||
long i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) ||
|
||||
put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
|
||||
put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask))
|
||||
return -EFAULT;
|
||||
}
|
||||
*written = count * sizeof(*p32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef struct xfs_fsop_bulkreq32 {
|
||||
#define xfs_inumbers_fmt_compat xfs_inumbers_fmt
|
||||
#define _PACKED
|
||||
|
||||
#endif
|
||||
|
||||
/* XFS_IOC_FSBULKSTAT and friends */
|
||||
|
||||
typedef struct compat_xfs_bstime {
|
||||
__s32 tv_sec; /* seconds */
|
||||
__s32 tv_nsec; /* and nanoseconds */
|
||||
} compat_xfs_bstime_t;
|
||||
|
||||
STATIC int xfs_bstime_store_compat(
|
||||
compat_xfs_bstime_t __user *p32,
|
||||
const xfs_bstime_t *p)
|
||||
{
|
||||
__s32 sec32;
|
||||
|
||||
sec32 = p->tv_sec;
|
||||
if (put_user(sec32, &p32->tv_sec) ||
|
||||
put_user(p->tv_nsec, &p32->tv_nsec))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct compat_xfs_bstat {
|
||||
__u64 bs_ino; /* inode number */
|
||||
__u16 bs_mode; /* type and mode */
|
||||
__u16 bs_nlink; /* number of links */
|
||||
__u32 bs_uid; /* user id */
|
||||
__u32 bs_gid; /* group id */
|
||||
__u32 bs_rdev; /* device value */
|
||||
__s32 bs_blksize; /* block size */
|
||||
__s64 bs_size; /* file size */
|
||||
compat_xfs_bstime_t bs_atime; /* access time */
|
||||
compat_xfs_bstime_t bs_mtime; /* modify time */
|
||||
compat_xfs_bstime_t bs_ctime; /* inode change time */
|
||||
int64_t bs_blocks; /* number of blocks */
|
||||
__u32 bs_xflags; /* extended flags */
|
||||
__s32 bs_extsize; /* extent size */
|
||||
__s32 bs_extents; /* number of extents */
|
||||
__u32 bs_gen; /* generation count */
|
||||
__u16 bs_projid; /* project id */
|
||||
unsigned char bs_pad[14]; /* pad space, unused */
|
||||
__u32 bs_dmevmask; /* DMIG event mask */
|
||||
__u16 bs_dmstate; /* DMIG state info */
|
||||
__u16 bs_aextents; /* attribute number of extents */
|
||||
} _PACKED compat_xfs_bstat_t;
|
||||
|
||||
STATIC int xfs_bulkstat_one_fmt_compat(
|
||||
void __user *ubuffer,
|
||||
const xfs_bstat_t *buffer)
|
||||
{
|
||||
compat_xfs_bstat_t __user *p32 = ubuffer;
|
||||
|
||||
if (put_user(buffer->bs_ino, &p32->bs_ino) ||
|
||||
put_user(buffer->bs_mode, &p32->bs_mode) ||
|
||||
put_user(buffer->bs_nlink, &p32->bs_nlink) ||
|
||||
put_user(buffer->bs_uid, &p32->bs_uid) ||
|
||||
put_user(buffer->bs_gid, &p32->bs_gid) ||
|
||||
put_user(buffer->bs_rdev, &p32->bs_rdev) ||
|
||||
put_user(buffer->bs_blksize, &p32->bs_blksize) ||
|
||||
put_user(buffer->bs_size, &p32->bs_size) ||
|
||||
xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) ||
|
||||
xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) ||
|
||||
xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) ||
|
||||
put_user(buffer->bs_blocks, &p32->bs_blocks) ||
|
||||
put_user(buffer->bs_xflags, &p32->bs_xflags) ||
|
||||
put_user(buffer->bs_extsize, &p32->bs_extsize) ||
|
||||
put_user(buffer->bs_extents, &p32->bs_extents) ||
|
||||
put_user(buffer->bs_gen, &p32->bs_gen) ||
|
||||
put_user(buffer->bs_projid, &p32->bs_projid) ||
|
||||
put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) ||
|
||||
put_user(buffer->bs_dmstate, &p32->bs_dmstate) ||
|
||||
put_user(buffer->bs_aextents, &p32->bs_aextents))
|
||||
return -EFAULT;
|
||||
return sizeof(*p32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct compat_xfs_fsop_bulkreq {
|
||||
compat_uptr_t lastip; /* last inode # pointer */
|
||||
__s32 icount; /* count of entries in buffer */
|
||||
compat_uptr_t ubuffer; /* user buffer for inode desc. */
|
||||
__s32 ocount; /* output count pointer */
|
||||
} xfs_fsop_bulkreq32_t;
|
||||
compat_uptr_t ocount; /* output count pointer */
|
||||
} compat_xfs_fsop_bulkreq_t;
|
||||
|
||||
STATIC unsigned long
|
||||
xfs_ioctl32_bulkstat(
|
||||
unsigned long arg)
|
||||
#define XFS_IOC_FSBULKSTAT_32 \
|
||||
_IOWR('X', 101, struct compat_xfs_fsop_bulkreq)
|
||||
#define XFS_IOC_FSBULKSTAT_SINGLE_32 \
|
||||
_IOWR('X', 102, struct compat_xfs_fsop_bulkreq)
|
||||
#define XFS_IOC_FSINUMBERS_32 \
|
||||
_IOWR('X', 103, struct compat_xfs_fsop_bulkreq)
|
||||
|
||||
/* copied from xfs_ioctl.c */
|
||||
STATIC int
|
||||
xfs_ioc_bulkstat_compat(
|
||||
xfs_mount_t *mp,
|
||||
unsigned int cmd,
|
||||
void __user *arg)
|
||||
{
|
||||
xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg;
|
||||
xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
compat_xfs_fsop_bulkreq_t __user *p32 = (void __user *)arg;
|
||||
u32 addr;
|
||||
xfs_fsop_bulkreq_t bulkreq;
|
||||
int count; /* # of records returned */
|
||||
xfs_ino_t inlast; /* last inode number */
|
||||
int done;
|
||||
int error;
|
||||
|
||||
if (get_user(addr, &p32->lastip) ||
|
||||
put_user(compat_ptr(addr), &p->lastip) ||
|
||||
copy_in_user(&p->icount, &p32->icount, sizeof(s32)) ||
|
||||
get_user(addr, &p32->ubuffer) ||
|
||||
put_user(compat_ptr(addr), &p->ubuffer) ||
|
||||
get_user(addr, &p32->ocount) ||
|
||||
put_user(compat_ptr(addr), &p->ocount))
|
||||
/* done = 1 if there are more stats to get and if bulkstat */
|
||||
/* should be called again (unused here, but used in dmapi) */
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (XFS_FORCED_SHUTDOWN(mp))
|
||||
return -XFS_ERROR(EIO);
|
||||
|
||||
if (get_user(addr, &p32->lastip))
|
||||
return -EFAULT;
|
||||
bulkreq.lastip = compat_ptr(addr);
|
||||
if (get_user(bulkreq.icount, &p32->icount) ||
|
||||
get_user(addr, &p32->ubuffer))
|
||||
return -EFAULT;
|
||||
bulkreq.ubuffer = compat_ptr(addr);
|
||||
if (get_user(addr, &p32->ocount))
|
||||
return -EFAULT;
|
||||
bulkreq.ocount = compat_ptr(addr);
|
||||
|
||||
if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
|
||||
return -XFS_ERROR(EFAULT);
|
||||
|
||||
if ((count = bulkreq.icount) <= 0)
|
||||
return -XFS_ERROR(EINVAL);
|
||||
|
||||
if (cmd == XFS_IOC_FSINUMBERS)
|
||||
error = xfs_inumbers(mp, &inlast, &count,
|
||||
bulkreq.ubuffer, xfs_inumbers_fmt_compat);
|
||||
else {
|
||||
/* declare a var to get a warning in case the type changes */
|
||||
bulkstat_one_fmt_pf formatter = xfs_bulkstat_one_fmt_compat;
|
||||
error = xfs_bulkstat(mp, &inlast, &count,
|
||||
xfs_bulkstat_one, formatter,
|
||||
sizeof(compat_xfs_bstat_t), bulkreq.ubuffer,
|
||||
BULKSTAT_FG_QUICK, &done);
|
||||
}
|
||||
if (error)
|
||||
return -error;
|
||||
|
||||
if (bulkreq.ocount != NULL) {
|
||||
if (copy_to_user(bulkreq.lastip, &inlast,
|
||||
sizeof(xfs_ino_t)))
|
||||
return -XFS_ERROR(EFAULT);
|
||||
|
||||
if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
|
||||
return -XFS_ERROR(EFAULT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct compat_xfs_fsop_handlereq {
|
||||
__u32 fd; /* fd for FD_TO_HANDLE */
|
||||
compat_uptr_t path; /* user pathname */
|
||||
__u32 oflags; /* open flags */
|
||||
compat_uptr_t ihandle; /* user supplied handle */
|
||||
__u32 ihandlen; /* user supplied length */
|
||||
compat_uptr_t ohandle; /* user buffer for handle */
|
||||
compat_uptr_t ohandlen; /* user buffer length */
|
||||
} compat_xfs_fsop_handlereq_t;
|
||||
|
||||
#define XFS_IOC_PATH_TO_FSHANDLE_32 \
|
||||
_IOWR('X', 104, struct compat_xfs_fsop_handlereq)
|
||||
#define XFS_IOC_PATH_TO_HANDLE_32 \
|
||||
_IOWR('X', 105, struct compat_xfs_fsop_handlereq)
|
||||
#define XFS_IOC_FD_TO_HANDLE_32 \
|
||||
_IOWR('X', 106, struct compat_xfs_fsop_handlereq)
|
||||
#define XFS_IOC_OPEN_BY_HANDLE_32 \
|
||||
_IOWR('X', 107, struct compat_xfs_fsop_handlereq)
|
||||
#define XFS_IOC_READLINK_BY_HANDLE_32 \
|
||||
_IOWR('X', 108, struct compat_xfs_fsop_handlereq)
|
||||
|
||||
STATIC unsigned long xfs_ioctl32_fshandle(unsigned long arg)
|
||||
{
|
||||
compat_xfs_fsop_handlereq_t __user *p32 = (void __user *)arg;
|
||||
xfs_fsop_handlereq_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
u32 addr;
|
||||
|
||||
if (copy_in_user(&p->fd, &p32->fd, sizeof(__u32)) ||
|
||||
get_user(addr, &p32->path) ||
|
||||
put_user(compat_ptr(addr), &p->path) ||
|
||||
copy_in_user(&p->oflags, &p32->oflags, sizeof(__u32)) ||
|
||||
get_user(addr, &p32->ihandle) ||
|
||||
put_user(compat_ptr(addr), &p->ihandle) ||
|
||||
copy_in_user(&p->ihandlen, &p32->ihandlen, sizeof(__u32)) ||
|
||||
get_user(addr, &p32->ohandle) ||
|
||||
put_user(compat_ptr(addr), &p->ohandle) ||
|
||||
get_user(addr, &p32->ohandlen) ||
|
||||
put_user(compat_ptr(addr), &p->ohandlen))
|
||||
return -EFAULT;
|
||||
|
||||
return (unsigned long)p;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
STATIC long
|
||||
xfs_compat_ioctl(
|
||||
|
@ -118,7 +375,6 @@ xfs_compat_ioctl(
|
|||
|
||||
switch (cmd) {
|
||||
case XFS_IOC_DIOINFO:
|
||||
case XFS_IOC_FSGEOMETRY_V1:
|
||||
case XFS_IOC_FSGEOMETRY:
|
||||
case XFS_IOC_GETVERSION:
|
||||
case XFS_IOC_GETXFLAGS:
|
||||
|
@ -131,12 +387,7 @@ xfs_compat_ioctl(
|
|||
case XFS_IOC_GETBMAPA:
|
||||
case XFS_IOC_GETBMAPX:
|
||||
/* not handled
|
||||
case XFS_IOC_FD_TO_HANDLE:
|
||||
case XFS_IOC_PATH_TO_HANDLE:
|
||||
case XFS_IOC_PATH_TO_FSHANDLE:
|
||||
case XFS_IOC_OPEN_BY_HANDLE:
|
||||
case XFS_IOC_FSSETDM_BY_HANDLE:
|
||||
case XFS_IOC_READLINK_BY_HANDLE:
|
||||
case XFS_IOC_ATTRLIST_BY_HANDLE:
|
||||
case XFS_IOC_ATTRMULTI_BY_HANDLE:
|
||||
*/
|
||||
|
@ -166,6 +417,10 @@ xfs_compat_ioctl(
|
|||
arg = xfs_ioctl32_flock(arg);
|
||||
cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
|
||||
break;
|
||||
case XFS_IOC_FSGEOMETRY_V1_32:
|
||||
arg = xfs_ioctl32_geom_v1(arg);
|
||||
cmd = _NATIVE_IOC(cmd, struct xfs_fsop_geom_v1);
|
||||
break;
|
||||
|
||||
#else /* These are handled fine if no alignment issues */
|
||||
case XFS_IOC_ALLOCSP:
|
||||
|
@ -176,18 +431,28 @@ xfs_compat_ioctl(
|
|||
case XFS_IOC_FREESP64:
|
||||
case XFS_IOC_RESVSP64:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
case XFS_IOC_FSGEOMETRY_V1:
|
||||
break;
|
||||
|
||||
/* xfs_bstat_t still has wrong u32 vs u64 alignment */
|
||||
case XFS_IOC_SWAPEXT:
|
||||
break;
|
||||
|
||||
case XFS_IOC_FSBULKSTAT_SINGLE:
|
||||
case XFS_IOC_FSBULKSTAT:
|
||||
case XFS_IOC_FSINUMBERS:
|
||||
arg = xfs_ioctl32_bulkstat(arg);
|
||||
break;
|
||||
#endif
|
||||
case XFS_IOC_FSBULKSTAT_32:
|
||||
case XFS_IOC_FSBULKSTAT_SINGLE_32:
|
||||
case XFS_IOC_FSINUMBERS_32:
|
||||
cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq);
|
||||
return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount,
|
||||
cmd, (void*)arg);
|
||||
case XFS_IOC_FD_TO_HANDLE_32:
|
||||
case XFS_IOC_PATH_TO_HANDLE_32:
|
||||
case XFS_IOC_PATH_TO_FSHANDLE_32:
|
||||
case XFS_IOC_OPEN_BY_HANDLE_32:
|
||||
case XFS_IOC_READLINK_BY_HANDLE_32:
|
||||
arg = xfs_ioctl32_fshandle(arg);
|
||||
cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq);
|
||||
break;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@
|
|||
#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
|
||||
#define xfs_rotorstep xfs_params.rotorstep.val
|
||||
#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val
|
||||
#define xfs_fstrm_centisecs xfs_params.fstrm_timer.val
|
||||
|
||||
#define current_cpu() (raw_smp_processor_id())
|
||||
#define current_pid() (current->pid)
|
||||
|
|
|
@ -547,7 +547,8 @@ vfs_sync_worker(
|
|||
|
||||
if (!(vfsp->vfs_flag & VFS_RDONLY))
|
||||
error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
|
||||
SYNC_ATTR | SYNC_REFCACHE, NULL);
|
||||
SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER,
|
||||
NULL);
|
||||
vfsp->vfs_sync_seq++;
|
||||
wake_up(&vfsp->vfs_wait_single_sync_task);
|
||||
}
|
||||
|
@ -663,7 +664,7 @@ xfs_fs_sync_super(
|
|||
* occur here so don't bother flushing the buftarg (i.e
|
||||
* SYNC_QUIESCE) because it'll just get dirty again.
|
||||
*/
|
||||
flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT;
|
||||
flags = SYNC_DATA_QUIESCE;
|
||||
} else
|
||||
flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
|
||||
|
||||
|
|
|
@ -210,6 +210,17 @@ static ctl_table xfs_table[] = {
|
|||
.extra1 = &xfs_params.inherit_nodfrg.min,
|
||||
.extra2 = &xfs_params.inherit_nodfrg.max
|
||||
},
|
||||
{
|
||||
.ctl_name = XFS_FILESTREAM_TIMER,
|
||||
.procname = "filestream_centisecs",
|
||||
.data = &xfs_params.fstrm_timer.val,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.extra1 = &xfs_params.fstrm_timer.min,
|
||||
.extra2 = &xfs_params.fstrm_timer.max,
|
||||
},
|
||||
/* please keep this the last entry */
|
||||
#ifdef CONFIG_PROC_FS
|
||||
{
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef struct xfs_param {
|
|||
xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */
|
||||
xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */
|
||||
xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
|
||||
xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */
|
||||
} xfs_param_t;
|
||||
|
||||
/*
|
||||
|
@ -86,6 +87,7 @@ enum {
|
|||
XFS_INHERIT_NOSYM = 19,
|
||||
XFS_ROTORSTEP = 20,
|
||||
XFS_INHERIT_NODFRG = 21,
|
||||
XFS_FILESTREAM_TIMER = 22,
|
||||
};
|
||||
|
||||
extern xfs_param_t xfs_params;
|
||||
|
|
|
@ -92,6 +92,21 @@ typedef enum {
|
|||
#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
|
||||
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
|
||||
#define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */
|
||||
#define SYNC_SUPER 0x0200 /* flush superblock to disk */
|
||||
|
||||
/*
|
||||
* When remounting a filesystem read-only or freezing the filesystem,
|
||||
* we have two phases to execute. This first phase is syncing the data
|
||||
* before we quiesce the fielsystem, and the second is flushing all the
|
||||
* inodes out after we've waited for all the transactions created by
|
||||
* the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
|
||||
* to ensure that the inodes are written to their location on disk
|
||||
* rather than just existing in transactions in the log. This means
|
||||
* after a quiesce there is no log replay required to write the inodes
|
||||
* to disk (this is the main difference between a sync and a quiesce).
|
||||
*/
|
||||
#define SYNC_DATA_QUIESCE (SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
|
||||
#define SYNC_INODE_QUIESCE (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
|
||||
|
||||
#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */
|
||||
#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */
|
||||
|
|
|
@ -129,10 +129,7 @@ typedef enum bhv_vchange {
|
|||
VCHANGE_FLAGS_IOEXCL_COUNT = 4
|
||||
} bhv_vchange_t;
|
||||
|
||||
typedef enum { L_FALSE, L_TRUE } lastclose_t;
|
||||
|
||||
typedef int (*vop_open_t)(bhv_desc_t *, struct cred *);
|
||||
typedef int (*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *);
|
||||
typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
|
||||
const struct iovec *, unsigned int,
|
||||
loff_t *, int, struct cred *);
|
||||
|
@ -200,7 +197,6 @@ typedef int (*vop_iflush_t)(bhv_desc_t *, int);
|
|||
typedef struct bhv_vnodeops {
|
||||
bhv_position_t vn_position; /* position within behavior chain */
|
||||
vop_open_t vop_open;
|
||||
vop_close_t vop_close;
|
||||
vop_read_t vop_read;
|
||||
vop_write_t vop_write;
|
||||
vop_splice_read_t vop_splice_read;
|
||||
|
@ -245,7 +241,6 @@ typedef struct bhv_vnodeops {
|
|||
#define VNHEAD(vp) ((vp)->v_bh.bh_first)
|
||||
#define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
|
||||
#define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr)
|
||||
#define bhv_vop_close(vp, f,last,cr) VOP(vop_close, vp)(VNHEAD(vp),f,last,cr)
|
||||
#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \
|
||||
VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
|
||||
#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \
|
||||
|
|
|
@ -62,10 +62,9 @@ uint ndquot;
|
|||
|
||||
kmem_zone_t *qm_dqzone;
|
||||
kmem_zone_t *qm_dqtrxzone;
|
||||
static kmem_shaker_t xfs_qm_shaker;
|
||||
static struct shrinker *xfs_qm_shaker;
|
||||
|
||||
static cred_t xfs_zerocr;
|
||||
static xfs_inode_t xfs_zeroino;
|
||||
|
||||
STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
|
||||
STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
|
||||
|
@ -150,7 +149,7 @@ xfs_Gqm_init(void)
|
|||
} else
|
||||
xqm->qm_dqzone = qm_dqzone;
|
||||
|
||||
xfs_qm_shaker = kmem_shake_register(xfs_qm_shake);
|
||||
xfs_qm_shaker = set_shrinker(DEFAULT_SEEKS, xfs_qm_shake);
|
||||
|
||||
/*
|
||||
* The t_dqinfo portion of transactions.
|
||||
|
@ -182,7 +181,7 @@ xfs_qm_destroy(
|
|||
|
||||
ASSERT(xqm != NULL);
|
||||
ASSERT(xqm->qm_nrefs == 0);
|
||||
kmem_shake_deregister(xfs_qm_shaker);
|
||||
remove_shrinker(xfs_qm_shaker);
|
||||
hsize = xqm->qm_dqhashmask + 1;
|
||||
for (i = 0; i < hsize; i++) {
|
||||
xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
|
||||
|
@ -1415,7 +1414,7 @@ xfs_qm_qino_alloc(
|
|||
return error;
|
||||
}
|
||||
|
||||
if ((error = xfs_dir_ialloc(&tp, &xfs_zeroino, S_IFREG, 1, 0,
|
||||
if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
|
||||
&xfs_zerocr, 0, 1, ip, &committed))) {
|
||||
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
|
||||
XFS_TRANS_ABORT);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define XFS_RW_TRACE 1
|
||||
#define XFS_BUF_TRACE 1
|
||||
#define XFS_VNODE_TRACE 1
|
||||
#define XFS_FILESTREAMS_TRACE 1
|
||||
#endif
|
||||
|
||||
#include <linux-2.6/xfs_linux.h>
|
||||
|
|
|
@ -68,6 +68,7 @@ typedef struct xfs_agf {
|
|||
__be32 agf_flcount; /* count of blocks in freelist */
|
||||
__be32 agf_freeblks; /* total free blocks */
|
||||
__be32 agf_longest; /* longest free space */
|
||||
__be32 agf_btreeblks; /* # of blocks held in AGF btrees */
|
||||
} xfs_agf_t;
|
||||
|
||||
#define XFS_AGF_MAGICNUM 0x00000001
|
||||
|
@ -81,7 +82,8 @@ typedef struct xfs_agf {
|
|||
#define XFS_AGF_FLCOUNT 0x00000100
|
||||
#define XFS_AGF_FREEBLKS 0x00000200
|
||||
#define XFS_AGF_LONGEST 0x00000400
|
||||
#define XFS_AGF_NUM_BITS 11
|
||||
#define XFS_AGF_BTREEBLKS 0x00000800
|
||||
#define XFS_AGF_NUM_BITS 12
|
||||
#define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1)
|
||||
|
||||
/* disk block (xfs_daddr_t) in the AG */
|
||||
|
@ -186,12 +188,15 @@ typedef struct xfs_perag
|
|||
__uint32_t pagf_flcount; /* count of blocks in freelist */
|
||||
xfs_extlen_t pagf_freeblks; /* total free blocks */
|
||||
xfs_extlen_t pagf_longest; /* longest free space */
|
||||
__uint32_t pagf_btreeblks; /* # of blocks held in AGF btrees */
|
||||
xfs_agino_t pagi_freecount; /* number of free inodes */
|
||||
xfs_agino_t pagi_count; /* number of allocated inodes */
|
||||
int pagb_count; /* pagb slots in use */
|
||||
#ifdef __KERNEL__
|
||||
lock_t pagb_lock; /* lock for pagb_list */
|
||||
#endif
|
||||
int pagb_count; /* pagb slots in use */
|
||||
xfs_perag_busy_t *pagb_list; /* unstable blocks */
|
||||
atomic_t pagf_fstrms; /* # of filestreams active in this AG */
|
||||
} xfs_perag_t;
|
||||
|
||||
#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
|
||||
|
|
|
@ -55,17 +55,17 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
|
|||
ktrace_t *xfs_alloc_trace_buf;
|
||||
|
||||
#define TRACE_ALLOC(s,a) \
|
||||
xfs_alloc_trace_alloc(fname, s, a, __LINE__)
|
||||
xfs_alloc_trace_alloc(__FUNCTION__, s, a, __LINE__)
|
||||
#define TRACE_FREE(s,a,b,x,f) \
|
||||
xfs_alloc_trace_free(fname, s, mp, a, b, x, f, __LINE__)
|
||||
xfs_alloc_trace_free(__FUNCTION__, s, mp, a, b, x, f, __LINE__)
|
||||
#define TRACE_MODAGF(s,a,f) \
|
||||
xfs_alloc_trace_modagf(fname, s, mp, a, f, __LINE__)
|
||||
#define TRACE_BUSY(fname,s,ag,agb,l,sl,tp) \
|
||||
xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
|
||||
#define TRACE_UNBUSY(fname,s,ag,sl,tp) \
|
||||
xfs_alloc_trace_busy(fname, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
|
||||
#define TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp) \
|
||||
xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
|
||||
xfs_alloc_trace_modagf(__FUNCTION__, s, mp, a, f, __LINE__)
|
||||
#define TRACE_BUSY(__FUNCTION__,s,ag,agb,l,sl,tp) \
|
||||
xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
|
||||
#define TRACE_UNBUSY(__FUNCTION__,s,ag,sl,tp) \
|
||||
xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
|
||||
#define TRACE_BUSYSEARCH(__FUNCTION__,s,ag,agb,l,sl,tp) \
|
||||
xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
|
||||
#else
|
||||
#define TRACE_ALLOC(s,a)
|
||||
#define TRACE_FREE(s,a,b,x,f)
|
||||
|
@ -420,7 +420,7 @@ xfs_alloc_read_agfl(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_alloc_trace_alloc(
|
||||
char *name, /* function tag string */
|
||||
const char *name, /* function tag string */
|
||||
char *str, /* additional string */
|
||||
xfs_alloc_arg_t *args, /* allocation argument structure */
|
||||
int line) /* source line number */
|
||||
|
@ -453,7 +453,7 @@ xfs_alloc_trace_alloc(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_alloc_trace_free(
|
||||
char *name, /* function tag string */
|
||||
const char *name, /* function tag string */
|
||||
char *str, /* additional string */
|
||||
xfs_mount_t *mp, /* file system mount point */
|
||||
xfs_agnumber_t agno, /* allocation group number */
|
||||
|
@ -479,7 +479,7 @@ xfs_alloc_trace_free(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_alloc_trace_modagf(
|
||||
char *name, /* function tag string */
|
||||
const char *name, /* function tag string */
|
||||
char *str, /* additional string */
|
||||
xfs_mount_t *mp, /* file system mount point */
|
||||
xfs_agf_t *agf, /* new agf value */
|
||||
|
@ -507,7 +507,7 @@ xfs_alloc_trace_modagf(
|
|||
|
||||
STATIC void
|
||||
xfs_alloc_trace_busy(
|
||||
char *name, /* function tag string */
|
||||
const char *name, /* function tag string */
|
||||
char *str, /* additional string */
|
||||
xfs_mount_t *mp, /* file system mount point */
|
||||
xfs_agnumber_t agno, /* allocation group number */
|
||||
|
@ -549,9 +549,6 @@ xfs_alloc_ag_vextent(
|
|||
xfs_alloc_arg_t *args) /* argument structure for allocation */
|
||||
{
|
||||
int error=0;
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_ag_vextent";
|
||||
#endif
|
||||
|
||||
ASSERT(args->minlen > 0);
|
||||
ASSERT(args->maxlen > 0);
|
||||
|
@ -635,9 +632,6 @@ xfs_alloc_ag_vextent_exact(
|
|||
xfs_agblock_t fbno; /* start block of found extent */
|
||||
xfs_agblock_t fend; /* end block of found extent */
|
||||
xfs_extlen_t flen; /* length of found extent */
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_ag_vextent_exact";
|
||||
#endif
|
||||
int i; /* success/failure of operation */
|
||||
xfs_agblock_t maxend; /* end of maximal extent */
|
||||
xfs_agblock_t minend; /* end of minimal extent */
|
||||
|
@ -737,9 +731,6 @@ xfs_alloc_ag_vextent_near(
|
|||
xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */
|
||||
xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */
|
||||
xfs_btree_cur_t *cnt_cur; /* cursor for count btree */
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_ag_vextent_near";
|
||||
#endif
|
||||
xfs_agblock_t gtbno; /* start bno of right side entry */
|
||||
xfs_agblock_t gtbnoa; /* aligned ... */
|
||||
xfs_extlen_t gtdiff; /* difference to right side entry */
|
||||
|
@ -1270,9 +1261,6 @@ xfs_alloc_ag_vextent_size(
|
|||
int error; /* error result */
|
||||
xfs_agblock_t fbno; /* start of found freespace */
|
||||
xfs_extlen_t flen; /* length of found freespace */
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_ag_vextent_size";
|
||||
#endif
|
||||
int i; /* temp status variable */
|
||||
xfs_agblock_t rbno; /* returned block number */
|
||||
xfs_extlen_t rlen; /* length of returned extent */
|
||||
|
@ -1427,9 +1415,6 @@ xfs_alloc_ag_vextent_small(
|
|||
int error;
|
||||
xfs_agblock_t fbno;
|
||||
xfs_extlen_t flen;
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_ag_vextent_small";
|
||||
#endif
|
||||
int i;
|
||||
|
||||
if ((error = xfs_alloc_decrement(ccur, 0, &i)))
|
||||
|
@ -1447,7 +1432,8 @@ xfs_alloc_ag_vextent_small(
|
|||
else if (args->minlen == 1 && args->alignment == 1 && !args->isfl &&
|
||||
(be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount)
|
||||
> args->minleft)) {
|
||||
if ((error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno)))
|
||||
error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0);
|
||||
if (error)
|
||||
goto error0;
|
||||
if (fbno != NULLAGBLOCK) {
|
||||
if (args->userdata) {
|
||||
|
@ -1515,9 +1501,6 @@ xfs_free_ag_extent(
|
|||
xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */
|
||||
xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_free_ag_extent";
|
||||
#endif
|
||||
xfs_agblock_t gtbno; /* start of right neighbor block */
|
||||
xfs_extlen_t gtlen; /* length of right neighbor block */
|
||||
int haveleft; /* have a left neighbor block */
|
||||
|
@ -1923,7 +1906,8 @@ xfs_alloc_fix_freelist(
|
|||
while (be32_to_cpu(agf->agf_flcount) > need) {
|
||||
xfs_buf_t *bp;
|
||||
|
||||
if ((error = xfs_alloc_get_freelist(tp, agbp, &bno)))
|
||||
error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
|
||||
if (error)
|
||||
return error;
|
||||
if ((error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1)))
|
||||
return error;
|
||||
|
@ -1973,8 +1957,9 @@ xfs_alloc_fix_freelist(
|
|||
* Put each allocated block on the list.
|
||||
*/
|
||||
for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) {
|
||||
if ((error = xfs_alloc_put_freelist(tp, agbp, agflbp,
|
||||
bno)))
|
||||
error = xfs_alloc_put_freelist(tp, agbp,
|
||||
agflbp, bno, 0);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
@ -1991,16 +1976,15 @@ int /* error */
|
|||
xfs_alloc_get_freelist(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_buf_t *agbp, /* buffer containing the agf structure */
|
||||
xfs_agblock_t *bnop) /* block address retrieved from freelist */
|
||||
xfs_agblock_t *bnop, /* block address retrieved from freelist */
|
||||
int btreeblk) /* destination is a AGF btree */
|
||||
{
|
||||
xfs_agf_t *agf; /* a.g. freespace structure */
|
||||
xfs_agfl_t *agfl; /* a.g. freelist structure */
|
||||
xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */
|
||||
xfs_agblock_t bno; /* block number returned */
|
||||
int error;
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_get_freelist";
|
||||
#endif
|
||||
int logflags;
|
||||
xfs_mount_t *mp; /* mount structure */
|
||||
xfs_perag_t *pag; /* per allocation group data */
|
||||
|
||||
|
@ -2032,8 +2016,16 @@ xfs_alloc_get_freelist(
|
|||
be32_add(&agf->agf_flcount, -1);
|
||||
xfs_trans_agflist_delta(tp, -1);
|
||||
pag->pagf_flcount--;
|
||||
TRACE_MODAGF(NULL, agf, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
|
||||
xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
|
||||
|
||||
logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
|
||||
if (btreeblk) {
|
||||
be32_add(&agf->agf_btreeblks, 1);
|
||||
pag->pagf_btreeblks++;
|
||||
logflags |= XFS_AGF_BTREEBLKS;
|
||||
}
|
||||
|
||||
TRACE_MODAGF(NULL, agf, logflags);
|
||||
xfs_alloc_log_agf(tp, agbp, logflags);
|
||||
*bnop = bno;
|
||||
|
||||
/*
|
||||
|
@ -2071,6 +2063,7 @@ xfs_alloc_log_agf(
|
|||
offsetof(xfs_agf_t, agf_flcount),
|
||||
offsetof(xfs_agf_t, agf_freeblks),
|
||||
offsetof(xfs_agf_t, agf_longest),
|
||||
offsetof(xfs_agf_t, agf_btreeblks),
|
||||
sizeof(xfs_agf_t)
|
||||
};
|
||||
|
||||
|
@ -2106,15 +2099,14 @@ xfs_alloc_put_freelist(
|
|||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_buf_t *agbp, /* buffer for a.g. freelist header */
|
||||
xfs_buf_t *agflbp,/* buffer for a.g. free block array */
|
||||
xfs_agblock_t bno) /* block being freed */
|
||||
xfs_agblock_t bno, /* block being freed */
|
||||
int btreeblk) /* block came from a AGF btree */
|
||||
{
|
||||
xfs_agf_t *agf; /* a.g. freespace structure */
|
||||
xfs_agfl_t *agfl; /* a.g. free block array */
|
||||
__be32 *blockp;/* pointer to array entry */
|
||||
int error;
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_put_freelist";
|
||||
#endif
|
||||
int logflags;
|
||||
xfs_mount_t *mp; /* mount structure */
|
||||
xfs_perag_t *pag; /* per allocation group data */
|
||||
|
||||
|
@ -2132,11 +2124,22 @@ xfs_alloc_put_freelist(
|
|||
be32_add(&agf->agf_flcount, 1);
|
||||
xfs_trans_agflist_delta(tp, 1);
|
||||
pag->pagf_flcount++;
|
||||
|
||||
logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT;
|
||||
if (btreeblk) {
|
||||
be32_add(&agf->agf_btreeblks, -1);
|
||||
pag->pagf_btreeblks--;
|
||||
logflags |= XFS_AGF_BTREEBLKS;
|
||||
}
|
||||
|
||||
TRACE_MODAGF(NULL, agf, logflags);
|
||||
xfs_alloc_log_agf(tp, agbp, logflags);
|
||||
|
||||
ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
|
||||
blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
|
||||
*blockp = cpu_to_be32(bno);
|
||||
TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
|
||||
xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
|
||||
TRACE_MODAGF(NULL, agf, logflags);
|
||||
xfs_alloc_log_agf(tp, agbp, logflags);
|
||||
xfs_trans_log_buf(tp, agflbp,
|
||||
(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
|
||||
(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
|
||||
|
@ -2196,6 +2199,7 @@ xfs_alloc_read_agf(
|
|||
pag = &mp->m_perag[agno];
|
||||
if (!pag->pagf_init) {
|
||||
pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
|
||||
pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
|
||||
pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
|
||||
pag->pagf_longest = be32_to_cpu(agf->agf_longest);
|
||||
pag->pagf_levels[XFS_BTNUM_BNOi] =
|
||||
|
@ -2235,9 +2239,6 @@ xfs_alloc_vextent(
|
|||
xfs_agblock_t agsize; /* allocation group size */
|
||||
int error;
|
||||
int flags; /* XFS_ALLOC_FLAG_... locking flags */
|
||||
#ifdef XFS_ALLOC_TRACE
|
||||
static char fname[] = "xfs_alloc_vextent";
|
||||
#endif
|
||||
xfs_extlen_t minleft;/* minimum left value, temp copy */
|
||||
xfs_mount_t *mp; /* mount structure pointer */
|
||||
xfs_agnumber_t sagno; /* starting allocation group number */
|
||||
|
|
|
@ -136,7 +136,8 @@ int /* error */
|
|||
xfs_alloc_get_freelist(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
struct xfs_buf *agbp, /* buffer containing the agf structure */
|
||||
xfs_agblock_t *bnop); /* block address retrieved from freelist */
|
||||
xfs_agblock_t *bnop, /* block address retrieved from freelist */
|
||||
int btreeblk); /* destination is a AGF btree */
|
||||
|
||||
/*
|
||||
* Log the given fields from the agf structure.
|
||||
|
@ -165,7 +166,8 @@ xfs_alloc_put_freelist(
|
|||
struct xfs_trans *tp, /* transaction pointer */
|
||||
struct xfs_buf *agbp, /* buffer for a.g. freelist header */
|
||||
struct xfs_buf *agflbp,/* buffer for a.g. free block array */
|
||||
xfs_agblock_t bno); /* block being freed */
|
||||
xfs_agblock_t bno, /* block being freed */
|
||||
int btreeblk); /* owner was a AGF btree */
|
||||
|
||||
/*
|
||||
* Read in the allocation group header (free/alloc section).
|
||||
|
|
|
@ -226,8 +226,9 @@ xfs_alloc_delrec(
|
|||
/*
|
||||
* Put this buffer/block on the ag's freelist.
|
||||
*/
|
||||
if ((error = xfs_alloc_put_freelist(cur->bc_tp,
|
||||
cur->bc_private.a.agbp, NULL, bno)))
|
||||
error = xfs_alloc_put_freelist(cur->bc_tp,
|
||||
cur->bc_private.a.agbp, NULL, bno, 1);
|
||||
if (error)
|
||||
return error;
|
||||
/*
|
||||
* Since blocks move to the free list without the
|
||||
|
@ -549,8 +550,9 @@ xfs_alloc_delrec(
|
|||
/*
|
||||
* Free the deleting block by putting it on the freelist.
|
||||
*/
|
||||
if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
|
||||
NULL, rbno)))
|
||||
error = xfs_alloc_put_freelist(cur->bc_tp,
|
||||
cur->bc_private.a.agbp, NULL, rbno, 1);
|
||||
if (error)
|
||||
return error;
|
||||
/*
|
||||
* Since blocks move to the free list without the coordination
|
||||
|
@ -1320,8 +1322,9 @@ xfs_alloc_newroot(
|
|||
/*
|
||||
* Get a buffer from the freelist blocks, for the new root.
|
||||
*/
|
||||
if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
|
||||
&nbno)))
|
||||
error = xfs_alloc_get_freelist(cur->bc_tp,
|
||||
cur->bc_private.a.agbp, &nbno, 1);
|
||||
if (error)
|
||||
return error;
|
||||
/*
|
||||
* None available, we fail.
|
||||
|
@ -1604,8 +1607,9 @@ xfs_alloc_split(
|
|||
* Allocate the new block from the freelist.
|
||||
* If we can't do it, we're toast. Give up.
|
||||
*/
|
||||
if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
|
||||
&rbno)))
|
||||
error = xfs_alloc_get_freelist(cur->bc_tp,
|
||||
cur->bc_private.a.agbp, &rbno, 1);
|
||||
if (error)
|
||||
return error;
|
||||
if (rbno == NULLAGBLOCK) {
|
||||
*stat = 0;
|
||||
|
|
|
@ -65,44 +65,6 @@ static const char xfs_highbit[256] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Count of bits set in byte, 0..8.
|
||||
*/
|
||||
static const char xfs_countbit[256] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, /* 00 .. 07 */
|
||||
1, 2, 2, 3, 2, 3, 3, 4, /* 08 .. 0f */
|
||||
1, 2, 2, 3, 2, 3, 3, 4, /* 10 .. 17 */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 18 .. 1f */
|
||||
1, 2, 2, 3, 2, 3, 3, 4, /* 20 .. 27 */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 28 .. 2f */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 30 .. 37 */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* 38 .. 3f */
|
||||
1, 2, 2, 3, 2, 3, 3, 4, /* 40 .. 47 */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 48 .. 4f */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 50 .. 57 */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* 58 .. 5f */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 60 .. 67 */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* 68 .. 6f */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* 70 .. 77 */
|
||||
4, 5, 5, 6, 5, 6, 6, 7, /* 78 .. 7f */
|
||||
1, 2, 2, 3, 2, 3, 3, 4, /* 80 .. 87 */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 88 .. 8f */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* 90 .. 97 */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* 98 .. 9f */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* a0 .. a7 */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* a8 .. af */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* b0 .. b7 */
|
||||
4, 5, 5, 6, 5, 6, 6, 7, /* b8 .. bf */
|
||||
2, 3, 3, 4, 3, 4, 4, 5, /* c0 .. c7 */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* c8 .. cf */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* d0 .. d7 */
|
||||
4, 5, 5, 6, 5, 6, 6, 7, /* d8 .. df */
|
||||
3, 4, 4, 5, 4, 5, 5, 6, /* e0 .. e7 */
|
||||
4, 5, 5, 6, 5, 6, 6, 7, /* e8 .. ef */
|
||||
4, 5, 5, 6, 5, 6, 6, 7, /* f0 .. f7 */
|
||||
5, 6, 6, 7, 6, 7, 7, 8, /* f8 .. ff */
|
||||
};
|
||||
|
||||
/*
|
||||
* xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
|
||||
*/
|
||||
|
@ -167,56 +129,21 @@ xfs_highbit64(
|
|||
|
||||
|
||||
/*
|
||||
* Count the number of bits set in the bitmap starting with bit
|
||||
* start_bit. Size is the size of the bitmap in words.
|
||||
*
|
||||
* Do the counting by mapping a byte value to the number of set
|
||||
* bits for that value using the xfs_countbit array, i.e.
|
||||
* xfs_countbit[0] == 0, xfs_countbit[1] == 1, xfs_countbit[2] == 1,
|
||||
* xfs_countbit[3] == 2, etc.
|
||||
* Return whether bitmap is empty.
|
||||
* Size is number of words in the bitmap, which is padded to word boundary
|
||||
* Returns 1 for empty, 0 for non-empty.
|
||||
*/
|
||||
int
|
||||
xfs_count_bits(uint *map, uint size, uint start_bit)
|
||||
xfs_bitmap_empty(uint *map, uint size)
|
||||
{
|
||||
register int bits;
|
||||
register unsigned char *bytep;
|
||||
register unsigned char *end_map;
|
||||
int byte_bit;
|
||||
uint i;
|
||||
uint ret = 0;
|
||||
|
||||
bits = 0;
|
||||
end_map = (char*)(map + size);
|
||||
bytep = (char*)(map + (start_bit & ~0x7));
|
||||
byte_bit = start_bit & 0x7;
|
||||
|
||||
/*
|
||||
* If the caller fell off the end of the map, return 0.
|
||||
*/
|
||||
if (bytep >= end_map) {
|
||||
return (0);
|
||||
for (i = 0; i < size; i++) {
|
||||
ret |= map[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* If start_bit is not byte aligned, then process the
|
||||
* first byte separately.
|
||||
*/
|
||||
if (byte_bit != 0) {
|
||||
/*
|
||||
* Shift off the bits we don't want to look at,
|
||||
* before indexing into xfs_countbit.
|
||||
*/
|
||||
bits += xfs_countbit[(*bytep >> byte_bit)];
|
||||
bytep++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the bits in each byte until the end of the bitmap.
|
||||
*/
|
||||
while (bytep < end_map) {
|
||||
bits += xfs_countbit[*bytep];
|
||||
bytep++;
|
||||
}
|
||||
|
||||
return (bits);
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -55,8 +55,8 @@ extern int xfs_lowbit64(__uint64_t v);
|
|||
/* Get high bit set out of 64-bit argument, -1 if none set */
|
||||
extern int xfs_highbit64(__uint64_t);
|
||||
|
||||
/* Count set bits in map starting with start_bit */
|
||||
extern int xfs_count_bits(uint *map, uint size, uint start_bit);
|
||||
/* Return whether bitmap is empty (1 == empty) */
|
||||
extern int xfs_bitmap_empty(uint *map, uint size);
|
||||
|
||||
/* Count continuous one bits in map starting with start_bit */
|
||||
extern int xfs_contig_bits(uint *map, uint size, uint start_bit);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "xfs_quota.h"
|
||||
#include "xfs_trans_space.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_filestream.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -277,7 +278,7 @@ xfs_bmap_isaeof(
|
|||
STATIC void
|
||||
xfs_bmap_trace_addentry(
|
||||
int opcode, /* operation */
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry(ies) */
|
||||
|
@ -291,7 +292,7 @@ xfs_bmap_trace_addentry(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_delete(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry(entries) deleted */
|
||||
|
@ -304,7 +305,7 @@ xfs_bmap_trace_delete(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_insert(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry(entries) inserted */
|
||||
|
@ -318,7 +319,7 @@ xfs_bmap_trace_insert(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_post_update(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry updated */
|
||||
|
@ -329,17 +330,25 @@ xfs_bmap_trace_post_update(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_pre_update(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry to be updated */
|
||||
int whichfork); /* data or attr fork */
|
||||
|
||||
#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w) \
|
||||
xfs_bmap_trace_delete(__FUNCTION__,d,ip,i,c,w)
|
||||
#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w) \
|
||||
xfs_bmap_trace_insert(__FUNCTION__,d,ip,i,c,r1,r2,w)
|
||||
#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w) \
|
||||
xfs_bmap_trace_post_update(__FUNCTION__,d,ip,i,w)
|
||||
#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w) \
|
||||
xfs_bmap_trace_pre_update(__FUNCTION__,d,ip,i,w)
|
||||
#else
|
||||
#define xfs_bmap_trace_delete(f,d,ip,i,c,w)
|
||||
#define xfs_bmap_trace_insert(f,d,ip,i,c,r1,r2,w)
|
||||
#define xfs_bmap_trace_post_update(f,d,ip,i,w)
|
||||
#define xfs_bmap_trace_pre_update(f,d,ip,i,w)
|
||||
#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
|
||||
#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
|
||||
#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)
|
||||
#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)
|
||||
#endif /* XFS_BMAP_TRACE */
|
||||
|
||||
/*
|
||||
|
@ -531,9 +540,6 @@ xfs_bmap_add_extent(
|
|||
xfs_filblks_t da_new; /* new count del alloc blocks used */
|
||||
xfs_filblks_t da_old; /* old count del alloc blocks used */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_add_extent";
|
||||
#endif
|
||||
xfs_ifork_t *ifp; /* inode fork ptr */
|
||||
int logflags; /* returned value */
|
||||
xfs_extnum_t nextents; /* number of extents in file now */
|
||||
|
@ -551,8 +557,8 @@ xfs_bmap_add_extent(
|
|||
* already extents in the list.
|
||||
*/
|
||||
if (nextents == 0) {
|
||||
xfs_bmap_trace_insert(fname, "insert empty", ip, 0, 1, new,
|
||||
NULL, whichfork);
|
||||
XFS_BMAP_TRACE_INSERT("insert empty", ip, 0, 1, new, NULL,
|
||||
whichfork);
|
||||
xfs_iext_insert(ifp, 0, 1, new);
|
||||
ASSERT(cur == NULL);
|
||||
ifp->if_lastex = 0;
|
||||
|
@ -710,9 +716,6 @@ xfs_bmap_add_extent_delay_real(
|
|||
int diff; /* temp value */
|
||||
xfs_bmbt_rec_t *ep; /* extent entry for idx */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_add_extent_delay_real";
|
||||
#endif
|
||||
int i; /* temp state */
|
||||
xfs_ifork_t *ifp; /* inode fork pointer */
|
||||
xfs_fileoff_t new_endoff; /* end offset of new entry */
|
||||
|
@ -808,15 +811,14 @@ xfs_bmap_add_extent_delay_real(
|
|||
* Filling in all of a previously delayed allocation extent.
|
||||
* The left and right neighbors are both contiguous with new.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
LEFT.br_blockcount + PREV.br_blockcount +
|
||||
RIGHT.br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
|
||||
xfs_iext_remove(ifp, idx, 2);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
ip->i_d.di_nextents--;
|
||||
|
@ -855,15 +857,14 @@ xfs_bmap_add_extent_delay_real(
|
|||
* Filling in all of a previously delayed allocation extent.
|
||||
* The left neighbor is contiguous, the right is not.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
LEFT.br_blockcount + PREV.br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
|
||||
xfs_iext_remove(ifp, idx, 1);
|
||||
if (cur == NULL)
|
||||
rval = XFS_ILOG_DEXT;
|
||||
|
@ -892,16 +893,13 @@ xfs_bmap_add_extent_delay_real(
|
|||
* Filling in all of a previously delayed allocation extent.
|
||||
* The right neighbor is contiguous, the left is not.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_startblock(ep, new->br_startblock);
|
||||
xfs_bmbt_set_blockcount(ep,
|
||||
PREV.br_blockcount + RIGHT.br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx;
|
||||
xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
|
||||
xfs_iext_remove(ifp, idx + 1, 1);
|
||||
if (cur == NULL)
|
||||
rval = XFS_ILOG_DEXT;
|
||||
|
@ -931,11 +929,9 @@ xfs_bmap_add_extent_delay_real(
|
|||
* Neither the left nor right neighbors are contiguous with
|
||||
* the new one.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_startblock(ep, new->br_startblock);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx;
|
||||
ip->i_d.di_nextents++;
|
||||
if (cur == NULL)
|
||||
|
@ -963,17 +959,14 @@ xfs_bmap_add_extent_delay_real(
|
|||
* Filling in the first part of a previous delayed allocation.
|
||||
* The left neighbor is contiguous.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
LEFT.br_blockcount + new->br_blockcount);
|
||||
xfs_bmbt_set_startoff(ep,
|
||||
PREV.br_startoff + new->br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
|
||||
temp = PREV.br_blockcount - new->br_blockcount;
|
||||
xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
if (cur == NULL)
|
||||
|
@ -995,8 +988,7 @@ xfs_bmap_add_extent_delay_real(
|
|||
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
|
||||
STARTBLOCKVAL(PREV.br_startblock));
|
||||
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
|
||||
xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
|
||||
*dnew = temp;
|
||||
/* DELTA: The boundary between two in-core extents moved. */
|
||||
temp = LEFT.br_startoff;
|
||||
|
@ -1009,11 +1001,11 @@ xfs_bmap_add_extent_delay_real(
|
|||
* Filling in the first part of a previous delayed allocation.
|
||||
* The left neighbor is not contiguous.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_startoff(ep, new_endoff);
|
||||
temp = PREV.br_blockcount - new->br_blockcount;
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
|
||||
XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
|
||||
XFS_DATA_FORK);
|
||||
xfs_iext_insert(ifp, idx, 1, new);
|
||||
ip->i_df.if_lastex = idx;
|
||||
|
@ -1046,8 +1038,7 @@ xfs_bmap_add_extent_delay_real(
|
|||
(cur ? cur->bc_private.b.allocated : 0));
|
||||
ep = xfs_iext_get_ext(ifp, idx + 1);
|
||||
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
|
||||
xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx + 1, XFS_DATA_FORK);
|
||||
*dnew = temp;
|
||||
/* DELTA: One in-core extent is split in two. */
|
||||
temp = PREV.br_startoff;
|
||||
|
@ -1060,17 +1051,14 @@ xfs_bmap_add_extent_delay_real(
|
|||
* The right neighbor is contiguous with the new allocation.
|
||||
*/
|
||||
temp = PREV.br_blockcount - new->br_blockcount;
|
||||
xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
|
||||
new->br_startoff, new->br_startblock,
|
||||
new->br_blockcount + RIGHT.br_blockcount,
|
||||
RIGHT.br_state);
|
||||
xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx + 1;
|
||||
if (cur == NULL)
|
||||
rval = XFS_ILOG_DEXT;
|
||||
|
@ -1091,8 +1079,7 @@ xfs_bmap_add_extent_delay_real(
|
|||
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
|
||||
STARTBLOCKVAL(PREV.br_startblock));
|
||||
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
|
||||
xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
|
||||
*dnew = temp;
|
||||
/* DELTA: The boundary between two in-core extents moved. */
|
||||
temp = PREV.br_startoff;
|
||||
|
@ -1106,10 +1093,10 @@ xfs_bmap_add_extent_delay_real(
|
|||
* The right neighbor is not contiguous.
|
||||
*/
|
||||
temp = PREV.br_blockcount - new->br_blockcount;
|
||||
xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
|
||||
new, NULL, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
|
||||
XFS_DATA_FORK);
|
||||
xfs_iext_insert(ifp, idx + 1, 1, new);
|
||||
ip->i_df.if_lastex = idx + 1;
|
||||
ip->i_d.di_nextents++;
|
||||
|
@ -1141,7 +1128,7 @@ xfs_bmap_add_extent_delay_real(
|
|||
(cur ? cur->bc_private.b.allocated : 0));
|
||||
ep = xfs_iext_get_ext(ifp, idx);
|
||||
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
|
||||
xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
|
||||
*dnew = temp;
|
||||
/* DELTA: One in-core extent is split in two. */
|
||||
temp = PREV.br_startoff;
|
||||
|
@ -1155,7 +1142,7 @@ xfs_bmap_add_extent_delay_real(
|
|||
* This case is avoided almost all the time.
|
||||
*/
|
||||
temp = new->br_startoff - PREV.br_startoff;
|
||||
xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
r[0] = *new;
|
||||
r[1].br_state = PREV.br_state;
|
||||
|
@ -1163,7 +1150,7 @@ xfs_bmap_add_extent_delay_real(
|
|||
r[1].br_startoff = new_endoff;
|
||||
temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
|
||||
r[1].br_blockcount = temp2;
|
||||
xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
|
||||
XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
|
||||
XFS_DATA_FORK);
|
||||
xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
|
||||
ip->i_df.if_lastex = idx + 1;
|
||||
|
@ -1222,13 +1209,11 @@ xfs_bmap_add_extent_delay_real(
|
|||
}
|
||||
ep = xfs_iext_get_ext(ifp, idx);
|
||||
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
|
||||
xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmap_trace_pre_update(fname, "0", ip, idx + 2,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2),
|
||||
NULLSTARTBLOCK((int)temp2));
|
||||
xfs_bmap_trace_post_update(fname, "0", ip, idx + 2,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
|
||||
*dnew = temp + temp2;
|
||||
/* DELTA: One in-core extent is split in three. */
|
||||
temp = PREV.br_startoff;
|
||||
|
@ -1287,9 +1272,6 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
xfs_btree_cur_t *cur; /* btree cursor */
|
||||
xfs_bmbt_rec_t *ep; /* extent entry for idx */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_add_extent_unwritten_real";
|
||||
#endif
|
||||
int i; /* temp state */
|
||||
xfs_ifork_t *ifp; /* inode fork pointer */
|
||||
xfs_fileoff_t new_endoff; /* end offset of new entry */
|
||||
|
@ -1390,15 +1372,14 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Setting all of a previous oldext extent to newext.
|
||||
* The left and right neighbors are both contiguous with new.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
LEFT.br_blockcount + PREV.br_blockcount +
|
||||
RIGHT.br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
|
||||
xfs_iext_remove(ifp, idx, 2);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
ip->i_d.di_nextents -= 2;
|
||||
|
@ -1441,15 +1422,14 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Setting all of a previous oldext extent to newext.
|
||||
* The left neighbor is contiguous, the right is not.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
LEFT.br_blockcount + PREV.br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
|
||||
xfs_iext_remove(ifp, idx, 1);
|
||||
ip->i_d.di_nextents--;
|
||||
if (cur == NULL)
|
||||
|
@ -1484,16 +1464,15 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Setting all of a previous oldext extent to newext.
|
||||
* The right neighbor is contiguous, the left is not.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep,
|
||||
PREV.br_blockcount + RIGHT.br_blockcount);
|
||||
xfs_bmbt_set_state(ep, newext);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx;
|
||||
xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
|
||||
xfs_iext_remove(ifp, idx + 1, 1);
|
||||
ip->i_d.di_nextents--;
|
||||
if (cur == NULL)
|
||||
|
@ -1529,10 +1508,10 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Neither the left nor right neighbors are contiguous with
|
||||
* the new one.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_state(ep, newext);
|
||||
xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx;
|
||||
if (cur == NULL)
|
||||
|
@ -1559,21 +1538,21 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Setting the first part of a previous oldext extent to newext.
|
||||
* The left neighbor is contiguous.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
LEFT.br_blockcount + new->br_blockcount);
|
||||
xfs_bmbt_set_startoff(ep,
|
||||
PREV.br_startoff + new->br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_startblock(ep,
|
||||
new->br_startblock + new->br_blockcount);
|
||||
xfs_bmbt_set_blockcount(ep,
|
||||
PREV.br_blockcount - new->br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
if (cur == NULL)
|
||||
|
@ -1610,15 +1589,15 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Setting the first part of a previous oldext extent to newext.
|
||||
* The left neighbor is not contiguous.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
|
||||
ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
|
||||
xfs_bmbt_set_startoff(ep, new_endoff);
|
||||
xfs_bmbt_set_blockcount(ep,
|
||||
PREV.br_blockcount - new->br_blockcount);
|
||||
xfs_bmbt_set_startblock(ep,
|
||||
new->br_startblock + new->br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LF", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
|
||||
XFS_DATA_FORK);
|
||||
xfs_iext_insert(ifp, idx, 1, new);
|
||||
ip->i_df.if_lastex = idx;
|
||||
|
@ -1653,18 +1632,18 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Setting the last part of a previous oldext extent to newext.
|
||||
* The right neighbor is contiguous with the new allocation.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep,
|
||||
PREV.br_blockcount - new->br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
|
||||
new->br_startoff, new->br_startblock,
|
||||
new->br_blockcount + RIGHT.br_blockcount, newext);
|
||||
xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1,
|
||||
XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx + 1;
|
||||
if (cur == NULL)
|
||||
|
@ -1700,12 +1679,12 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* Setting the last part of a previous oldext extent to newext.
|
||||
* The right neighbor is not contiguous.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep,
|
||||
PREV.br_blockcount - new->br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
|
||||
new, NULL, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
|
||||
XFS_DATA_FORK);
|
||||
xfs_iext_insert(ifp, idx + 1, 1, new);
|
||||
ip->i_df.if_lastex = idx + 1;
|
||||
ip->i_d.di_nextents++;
|
||||
|
@ -1744,17 +1723,17 @@ xfs_bmap_add_extent_unwritten_real(
|
|||
* newext. Contiguity is impossible here.
|
||||
* One extent becomes three extents.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(ep,
|
||||
new->br_startoff - PREV.br_startoff);
|
||||
xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
|
||||
r[0] = *new;
|
||||
r[1].br_startoff = new_endoff;
|
||||
r[1].br_blockcount =
|
||||
PREV.br_startoff + PREV.br_blockcount - new_endoff;
|
||||
r[1].br_startblock = new->br_startblock + new->br_blockcount;
|
||||
r[1].br_state = oldext;
|
||||
xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
|
||||
XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
|
||||
XFS_DATA_FORK);
|
||||
xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
|
||||
ip->i_df.if_lastex = idx + 1;
|
||||
|
@ -1845,9 +1824,6 @@ xfs_bmap_add_extent_hole_delay(
|
|||
int rsvd) /* OK to allocate reserved blocks */
|
||||
{
|
||||
xfs_bmbt_rec_t *ep; /* extent record for idx */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_add_extent_hole_delay";
|
||||
#endif
|
||||
xfs_ifork_t *ifp; /* inode fork pointer */
|
||||
xfs_bmbt_irec_t left; /* left neighbor extent entry */
|
||||
xfs_filblks_t newlen=0; /* new indirect size */
|
||||
|
@ -1919,7 +1895,7 @@ xfs_bmap_add_extent_hole_delay(
|
|||
*/
|
||||
temp = left.br_blockcount + new->br_blockcount +
|
||||
right.br_blockcount;
|
||||
xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
|
||||
oldlen = STARTBLOCKVAL(left.br_startblock) +
|
||||
|
@ -1928,10 +1904,9 @@ xfs_bmap_add_extent_hole_delay(
|
|||
newlen = xfs_bmap_worst_indlen(ip, temp);
|
||||
xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
|
||||
NULLSTARTBLOCK((int)newlen));
|
||||
xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmap_trace_delete(fname, "LC|RC", ip, idx, 1,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK);
|
||||
xfs_iext_remove(ifp, idx, 1);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
/* DELTA: Two in-core extents were replaced by one. */
|
||||
|
@ -1946,7 +1921,7 @@ xfs_bmap_add_extent_hole_delay(
|
|||
* Merge the new allocation with the left neighbor.
|
||||
*/
|
||||
temp = left.br_blockcount + new->br_blockcount;
|
||||
xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
|
||||
oldlen = STARTBLOCKVAL(left.br_startblock) +
|
||||
|
@ -1954,7 +1929,7 @@ xfs_bmap_add_extent_hole_delay(
|
|||
newlen = xfs_bmap_worst_indlen(ip, temp);
|
||||
xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
|
||||
NULLSTARTBLOCK((int)newlen));
|
||||
xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1,
|
||||
XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx - 1;
|
||||
/* DELTA: One in-core extent grew into a hole. */
|
||||
|
@ -1968,14 +1943,14 @@ xfs_bmap_add_extent_hole_delay(
|
|||
* on the right.
|
||||
* Merge the new allocation with the right neighbor.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "RC", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK);
|
||||
temp = new->br_blockcount + right.br_blockcount;
|
||||
oldlen = STARTBLOCKVAL(new->br_startblock) +
|
||||
STARTBLOCKVAL(right.br_startblock);
|
||||
newlen = xfs_bmap_worst_indlen(ip, temp);
|
||||
xfs_bmbt_set_allf(ep, new->br_startoff,
|
||||
NULLSTARTBLOCK((int)newlen), temp, right.br_state);
|
||||
xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK);
|
||||
ip->i_df.if_lastex = idx;
|
||||
/* DELTA: One in-core extent grew into a hole. */
|
||||
temp2 = temp;
|
||||
|
@ -1989,7 +1964,7 @@ xfs_bmap_add_extent_hole_delay(
|
|||
* Insert a new entry.
|
||||
*/
|
||||
oldlen = newlen = 0;
|
||||
xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
|
||||
XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL,
|
||||
XFS_DATA_FORK);
|
||||
xfs_iext_insert(ifp, idx, 1, new);
|
||||
ip->i_df.if_lastex = idx;
|
||||
|
@ -2039,9 +2014,6 @@ xfs_bmap_add_extent_hole_real(
|
|||
{
|
||||
xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_add_extent_hole_real";
|
||||
#endif
|
||||
int i; /* temp state */
|
||||
xfs_ifork_t *ifp; /* inode fork pointer */
|
||||
xfs_bmbt_irec_t left; /* left neighbor extent entry */
|
||||
|
@ -2118,15 +2090,14 @@ xfs_bmap_add_extent_hole_real(
|
|||
* left and on the right.
|
||||
* Merge all three into a single extent record.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
|
||||
whichfork);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
left.br_blockcount + new->br_blockcount +
|
||||
right.br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
|
||||
whichfork);
|
||||
xfs_bmap_trace_delete(fname, "LC|RC", ip,
|
||||
idx, 1, whichfork);
|
||||
XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, whichfork);
|
||||
xfs_iext_remove(ifp, idx, 1);
|
||||
ifp->if_lastex = idx - 1;
|
||||
XFS_IFORK_NEXT_SET(ip, whichfork,
|
||||
|
@ -2168,10 +2139,10 @@ xfs_bmap_add_extent_hole_real(
|
|||
* on the left.
|
||||
* Merge the new allocation with the left neighbor.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1, whichfork);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1, whichfork);
|
||||
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
|
||||
left.br_blockcount + new->br_blockcount);
|
||||
xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1, whichfork);
|
||||
ifp->if_lastex = idx - 1;
|
||||
if (cur == NULL) {
|
||||
rval = XFS_ILOG_FEXT(whichfork);
|
||||
|
@ -2202,11 +2173,11 @@ xfs_bmap_add_extent_hole_real(
|
|||
* on the right.
|
||||
* Merge the new allocation with the right neighbor.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "RC", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, whichfork);
|
||||
xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
|
||||
new->br_blockcount + right.br_blockcount,
|
||||
right.br_state);
|
||||
xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, whichfork);
|
||||
ifp->if_lastex = idx;
|
||||
if (cur == NULL) {
|
||||
rval = XFS_ILOG_FEXT(whichfork);
|
||||
|
@ -2237,8 +2208,7 @@ xfs_bmap_add_extent_hole_real(
|
|||
* real allocation.
|
||||
* Insert a new entry.
|
||||
*/
|
||||
xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
|
||||
whichfork);
|
||||
XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL, whichfork);
|
||||
xfs_iext_insert(ifp, idx, 1, new);
|
||||
ifp->if_lastex = idx;
|
||||
XFS_IFORK_NEXT_SET(ip, whichfork,
|
||||
|
@ -2605,12 +2575,10 @@ xfs_bmap_rtalloc(
|
|||
xfs_extlen_t prod = 0; /* product factor for allocators */
|
||||
xfs_extlen_t ralen = 0; /* realtime allocation length */
|
||||
xfs_extlen_t align; /* minimum allocation alignment */
|
||||
xfs_rtblock_t rtx; /* realtime extent number */
|
||||
xfs_rtblock_t rtb;
|
||||
|
||||
mp = ap->ip->i_mount;
|
||||
align = ap->ip->i_d.di_extsize ?
|
||||
ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
|
||||
align = xfs_get_extsz_hint(ap->ip);
|
||||
prod = align / mp->m_sb.sb_rextsize;
|
||||
error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
|
||||
align, 1, ap->eof, 0,
|
||||
|
@ -2644,6 +2612,8 @@ xfs_bmap_rtalloc(
|
|||
* pick an extent that will space things out in the rt area.
|
||||
*/
|
||||
if (ap->eof && ap->off == 0) {
|
||||
xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
|
||||
|
||||
error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -2715,9 +2685,7 @@ xfs_bmap_btalloc(
|
|||
int error;
|
||||
|
||||
mp = ap->ip->i_mount;
|
||||
align = (ap->userdata && ap->ip->i_d.di_extsize &&
|
||||
(ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
|
||||
ap->ip->i_d.di_extsize : 0;
|
||||
align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
|
||||
if (unlikely(align)) {
|
||||
error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
|
||||
align, 0, ap->eof, 0, ap->conv,
|
||||
|
@ -2727,9 +2695,15 @@ xfs_bmap_btalloc(
|
|||
}
|
||||
nullfb = ap->firstblock == NULLFSBLOCK;
|
||||
fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
|
||||
if (nullfb)
|
||||
ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
|
||||
else
|
||||
if (nullfb) {
|
||||
if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
|
||||
ag = xfs_filestream_lookup_ag(ap->ip);
|
||||
ag = (ag != NULLAGNUMBER) ? ag : 0;
|
||||
ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
|
||||
} else {
|
||||
ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
|
||||
}
|
||||
} else
|
||||
ap->rval = ap->firstblock;
|
||||
|
||||
xfs_bmap_adjacent(ap);
|
||||
|
@ -2753,13 +2727,22 @@ xfs_bmap_btalloc(
|
|||
args.firstblock = ap->firstblock;
|
||||
blen = 0;
|
||||
if (nullfb) {
|
||||
args.type = XFS_ALLOCTYPE_START_BNO;
|
||||
if (ap->userdata && xfs_inode_is_filestream(ap->ip))
|
||||
args.type = XFS_ALLOCTYPE_NEAR_BNO;
|
||||
else
|
||||
args.type = XFS_ALLOCTYPE_START_BNO;
|
||||
args.total = ap->total;
|
||||
|
||||
/*
|
||||
* Find the longest available space.
|
||||
* We're going to try for the whole allocation at once.
|
||||
* Search for an allocation group with a single extent
|
||||
* large enough for the request.
|
||||
*
|
||||
* If one isn't found, then adjust the minimum allocation
|
||||
* size to the largest space found.
|
||||
*/
|
||||
startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
|
||||
if (startag == NULLAGNUMBER)
|
||||
startag = ag = 0;
|
||||
notinit = 0;
|
||||
down_read(&mp->m_peraglock);
|
||||
while (blen < ap->alen) {
|
||||
|
@ -2785,6 +2768,35 @@ xfs_bmap_btalloc(
|
|||
blen = longest;
|
||||
} else
|
||||
notinit = 1;
|
||||
|
||||
if (xfs_inode_is_filestream(ap->ip)) {
|
||||
if (blen >= ap->alen)
|
||||
break;
|
||||
|
||||
if (ap->userdata) {
|
||||
/*
|
||||
* If startag is an invalid AG, we've
|
||||
* come here once before and
|
||||
* xfs_filestream_new_ag picked the
|
||||
* best currently available.
|
||||
*
|
||||
* Don't continue looping, since we
|
||||
* could loop forever.
|
||||
*/
|
||||
if (startag == NULLAGNUMBER)
|
||||
break;
|
||||
|
||||
error = xfs_filestream_new_ag(ap, &ag);
|
||||
if (error) {
|
||||
up_read(&mp->m_peraglock);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* loop again to set 'blen'*/
|
||||
startag = NULLAGNUMBER;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (++ag == mp->m_sb.sb_agcount)
|
||||
ag = 0;
|
||||
if (ag == startag)
|
||||
|
@ -2809,17 +2821,27 @@ xfs_bmap_btalloc(
|
|||
*/
|
||||
else
|
||||
args.minlen = ap->alen;
|
||||
|
||||
/*
|
||||
* set the failure fallback case to look in the selected
|
||||
* AG as the stream may have moved.
|
||||
*/
|
||||
if (xfs_inode_is_filestream(ap->ip))
|
||||
ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
|
||||
} else if (ap->low) {
|
||||
args.type = XFS_ALLOCTYPE_START_BNO;
|
||||
if (xfs_inode_is_filestream(ap->ip))
|
||||
args.type = XFS_ALLOCTYPE_FIRST_AG;
|
||||
else
|
||||
args.type = XFS_ALLOCTYPE_START_BNO;
|
||||
args.total = args.minlen = ap->minlen;
|
||||
} else {
|
||||
args.type = XFS_ALLOCTYPE_NEAR_BNO;
|
||||
args.total = ap->total;
|
||||
args.minlen = ap->minlen;
|
||||
}
|
||||
if (unlikely(ap->userdata && ap->ip->i_d.di_extsize &&
|
||||
(ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) {
|
||||
args.prod = ap->ip->i_d.di_extsize;
|
||||
/* apply extent size hints if obtained earlier */
|
||||
if (unlikely(align)) {
|
||||
args.prod = align;
|
||||
if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
|
||||
args.mod = (xfs_extlen_t)(args.prod - args.mod);
|
||||
} else if (mp->m_sb.sb_blocksize >= NBPP) {
|
||||
|
@ -3051,9 +3073,6 @@ xfs_bmap_del_extent(
|
|||
xfs_bmbt_rec_t *ep; /* current extent entry pointer */
|
||||
int error; /* error return value */
|
||||
int flags; /* inode logging flags */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_del_extent";
|
||||
#endif
|
||||
xfs_bmbt_irec_t got; /* current extent entry */
|
||||
xfs_fileoff_t got_endoff; /* first offset past got */
|
||||
int i; /* temp state */
|
||||
|
@ -3147,7 +3166,7 @@ xfs_bmap_del_extent(
|
|||
/*
|
||||
* Matches the whole extent. Delete the entry.
|
||||
*/
|
||||
xfs_bmap_trace_delete(fname, "3", ip, idx, 1, whichfork);
|
||||
XFS_BMAP_TRACE_DELETE("3", ip, idx, 1, whichfork);
|
||||
xfs_iext_remove(ifp, idx, 1);
|
||||
ifp->if_lastex = idx;
|
||||
if (delay)
|
||||
|
@ -3168,7 +3187,7 @@ xfs_bmap_del_extent(
|
|||
/*
|
||||
* Deleting the first part of the extent.
|
||||
*/
|
||||
xfs_bmap_trace_pre_update(fname, "2", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("2", ip, idx, whichfork);
|
||||
xfs_bmbt_set_startoff(ep, del_endoff);
|
||||
temp = got.br_blockcount - del->br_blockcount;
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
|
@ -3177,13 +3196,13 @@ xfs_bmap_del_extent(
|
|||
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
|
||||
da_old);
|
||||
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
|
||||
xfs_bmap_trace_post_update(fname, "2", ip, idx,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx,
|
||||
whichfork);
|
||||
da_new = temp;
|
||||
break;
|
||||
}
|
||||
xfs_bmbt_set_startblock(ep, del_endblock);
|
||||
xfs_bmap_trace_post_update(fname, "2", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx, whichfork);
|
||||
if (!cur) {
|
||||
flags |= XFS_ILOG_FEXT(whichfork);
|
||||
break;
|
||||
|
@ -3199,19 +3218,19 @@ xfs_bmap_del_extent(
|
|||
* Deleting the last part of the extent.
|
||||
*/
|
||||
temp = got.br_blockcount - del->br_blockcount;
|
||||
xfs_bmap_trace_pre_update(fname, "1", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("1", ip, idx, whichfork);
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
ifp->if_lastex = idx;
|
||||
if (delay) {
|
||||
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
|
||||
da_old);
|
||||
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
|
||||
xfs_bmap_trace_post_update(fname, "1", ip, idx,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx,
|
||||
whichfork);
|
||||
da_new = temp;
|
||||
break;
|
||||
}
|
||||
xfs_bmap_trace_post_update(fname, "1", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx, whichfork);
|
||||
if (!cur) {
|
||||
flags |= XFS_ILOG_FEXT(whichfork);
|
||||
break;
|
||||
|
@ -3228,7 +3247,7 @@ xfs_bmap_del_extent(
|
|||
* Deleting the middle of the extent.
|
||||
*/
|
||||
temp = del->br_startoff - got.br_startoff;
|
||||
xfs_bmap_trace_pre_update(fname, "0", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, whichfork);
|
||||
xfs_bmbt_set_blockcount(ep, temp);
|
||||
new.br_startoff = del_endoff;
|
||||
temp2 = got_endoff - del_endoff;
|
||||
|
@ -3315,8 +3334,8 @@ xfs_bmap_del_extent(
|
|||
}
|
||||
}
|
||||
}
|
||||
xfs_bmap_trace_post_update(fname, "0", ip, idx, whichfork);
|
||||
xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 1, &new, NULL,
|
||||
XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, whichfork);
|
||||
XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 1, &new, NULL,
|
||||
whichfork);
|
||||
xfs_iext_insert(ifp, idx + 1, 1, &new);
|
||||
ifp->if_lastex = idx + 1;
|
||||
|
@ -3556,9 +3575,6 @@ xfs_bmap_local_to_extents(
|
|||
{
|
||||
int error; /* error return value */
|
||||
int flags; /* logging flags returned */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_local_to_extents";
|
||||
#endif
|
||||
xfs_ifork_t *ifp; /* inode fork pointer */
|
||||
|
||||
/*
|
||||
|
@ -3613,7 +3629,7 @@ xfs_bmap_local_to_extents(
|
|||
xfs_iext_add(ifp, 0, 1);
|
||||
ep = xfs_iext_get_ext(ifp, 0);
|
||||
xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
|
||||
xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork);
|
||||
XFS_BMAP_TRACE_POST_UPDATE("new", ip, 0, whichfork);
|
||||
XFS_IFORK_NEXT_SET(ip, whichfork, 1);
|
||||
ip->i_d.di_nblocks = 1;
|
||||
XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip,
|
||||
|
@ -3736,7 +3752,7 @@ ktrace_t *xfs_bmap_trace_buf;
|
|||
STATIC void
|
||||
xfs_bmap_trace_addentry(
|
||||
int opcode, /* operation */
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry(ies) */
|
||||
|
@ -3795,7 +3811,7 @@ xfs_bmap_trace_addentry(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_delete(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry(entries) deleted */
|
||||
|
@ -3817,7 +3833,7 @@ xfs_bmap_trace_delete(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_insert(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry(entries) inserted */
|
||||
|
@ -3846,7 +3862,7 @@ xfs_bmap_trace_insert(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_post_update(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry updated */
|
||||
|
@ -3864,7 +3880,7 @@ xfs_bmap_trace_post_update(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmap_trace_pre_update(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
char *desc, /* operation description */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t idx, /* index of entry to be updated */
|
||||
|
@ -4481,9 +4497,6 @@ xfs_bmap_read_extents(
|
|||
xfs_buf_t *bp; /* buffer for "block" */
|
||||
int error; /* error return value */
|
||||
xfs_exntfmt_t exntf; /* XFS_EXTFMT_NOSTATE, if checking */
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_bmap_read_extents";
|
||||
#endif
|
||||
xfs_extnum_t i, j; /* index into the extents list */
|
||||
xfs_ifork_t *ifp; /* fork structure */
|
||||
int level; /* btree level, for checking */
|
||||
|
@ -4600,7 +4613,7 @@ xfs_bmap_read_extents(
|
|||
}
|
||||
ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
|
||||
ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
|
||||
xfs_bmap_trace_exlist(fname, ip, i, whichfork);
|
||||
XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
|
||||
return 0;
|
||||
error0:
|
||||
xfs_trans_brelse(tp, bp);
|
||||
|
@ -4613,7 +4626,7 @@ error0:
|
|||
*/
|
||||
void
|
||||
xfs_bmap_trace_exlist(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
xfs_inode_t *ip, /* incore inode pointer */
|
||||
xfs_extnum_t cnt, /* count of entries in the list */
|
||||
int whichfork) /* data or attr fork */
|
||||
|
@ -4628,7 +4641,7 @@ xfs_bmap_trace_exlist(
|
|||
for (idx = 0; idx < cnt; idx++) {
|
||||
ep = xfs_iext_get_ext(ifp, idx);
|
||||
xfs_bmbt_get_all(ep, &s);
|
||||
xfs_bmap_trace_insert(fname, "exlist", ip, idx, 1, &s, NULL,
|
||||
XFS_BMAP_TRACE_INSERT("exlist", ip, idx, 1, &s, NULL,
|
||||
whichfork);
|
||||
}
|
||||
}
|
||||
|
@ -4868,12 +4881,7 @@ xfs_bmapi(
|
|||
xfs_extlen_t extsz;
|
||||
|
||||
/* Figure out the extent size, adjust alen */
|
||||
if (rt) {
|
||||
if (!(extsz = ip->i_d.di_extsize))
|
||||
extsz = mp->m_sb.sb_rextsize;
|
||||
} else {
|
||||
extsz = ip->i_d.di_extsize;
|
||||
}
|
||||
extsz = xfs_get_extsz_hint(ip);
|
||||
if (extsz) {
|
||||
error = xfs_bmap_extsize_align(mp,
|
||||
&got, &prev, extsz,
|
||||
|
@ -5219,10 +5227,10 @@ xfs_bmapi(
|
|||
* Else go on to the next record.
|
||||
*/
|
||||
ep = xfs_iext_get_ext(ifp, ++lastx);
|
||||
if (lastx >= nextents) {
|
||||
prev = got;
|
||||
if (lastx >= nextents)
|
||||
eof = 1;
|
||||
prev = got;
|
||||
} else
|
||||
else
|
||||
xfs_bmbt_get_all(ep, &got);
|
||||
}
|
||||
ifp->if_lastex = lastx;
|
||||
|
@ -5813,8 +5821,7 @@ xfs_getbmap(
|
|||
ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
|
||||
return XFS_ERROR(EINVAL);
|
||||
if (whichfork == XFS_DATA_FORK) {
|
||||
if ((ip->i_d.di_extsize && (ip->i_d.di_flags &
|
||||
(XFS_DIFLAG_REALTIME|XFS_DIFLAG_EXTSIZE))) ||
|
||||
if (xfs_get_extsz_hint(ip) ||
|
||||
ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
|
||||
prealloced = 1;
|
||||
fixlen = XFS_MAXIOFFSET(mp);
|
||||
|
|
|
@ -144,12 +144,14 @@ extern ktrace_t *xfs_bmap_trace_buf;
|
|||
*/
|
||||
void
|
||||
xfs_bmap_trace_exlist(
|
||||
char *fname, /* function name */
|
||||
const char *fname, /* function name */
|
||||
struct xfs_inode *ip, /* incore inode pointer */
|
||||
xfs_extnum_t cnt, /* count of entries in list */
|
||||
int whichfork); /* data or attr fork */
|
||||
#define XFS_BMAP_TRACE_EXLIST(ip,c,w) \
|
||||
xfs_bmap_trace_exlist(__FUNCTION__,ip,c,w)
|
||||
#else
|
||||
#define xfs_bmap_trace_exlist(f,ip,c,w)
|
||||
#define XFS_BMAP_TRACE_EXLIST(ip,c,w)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -76,7 +76,7 @@ static char EXIT[] = "exit";
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_enter(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
char *s,
|
||||
int type,
|
||||
|
@ -117,7 +117,7 @@ xfs_bmbt_trace_enter(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_argbi(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
xfs_buf_t *b,
|
||||
int i,
|
||||
|
@ -134,7 +134,7 @@ xfs_bmbt_trace_argbi(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_argbii(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
xfs_buf_t *b,
|
||||
int i0,
|
||||
|
@ -153,7 +153,7 @@ xfs_bmbt_trace_argbii(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_argfffi(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
xfs_dfiloff_t o,
|
||||
xfs_dfsbno_t b,
|
||||
|
@ -172,7 +172,7 @@ xfs_bmbt_trace_argfffi(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_argi(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
int i,
|
||||
int line)
|
||||
|
@ -188,7 +188,7 @@ xfs_bmbt_trace_argi(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_argifk(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
int i,
|
||||
xfs_fsblock_t f,
|
||||
|
@ -206,7 +206,7 @@ xfs_bmbt_trace_argifk(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_argifr(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
int i,
|
||||
xfs_fsblock_t f,
|
||||
|
@ -235,7 +235,7 @@ xfs_bmbt_trace_argifr(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_argik(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
int i,
|
||||
xfs_bmbt_key_t *k,
|
||||
|
@ -255,7 +255,7 @@ xfs_bmbt_trace_argik(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_bmbt_trace_cursor(
|
||||
char *func,
|
||||
const char *func,
|
||||
xfs_btree_cur_t *cur,
|
||||
char *s,
|
||||
int line)
|
||||
|
@ -274,21 +274,21 @@ xfs_bmbt_trace_cursor(
|
|||
}
|
||||
|
||||
#define XFS_BMBT_TRACE_ARGBI(c,b,i) \
|
||||
xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
|
||||
xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__)
|
||||
#define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \
|
||||
xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
|
||||
xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__)
|
||||
#define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \
|
||||
xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
|
||||
xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__)
|
||||
#define XFS_BMBT_TRACE_ARGI(c,i) \
|
||||
xfs_bmbt_trace_argi(fname, c, i, __LINE__)
|
||||
xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__)
|
||||
#define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \
|
||||
xfs_bmbt_trace_argifk(fname, c, i, f, s, __LINE__)
|
||||
xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__)
|
||||
#define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \
|
||||
xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
|
||||
xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__)
|
||||
#define XFS_BMBT_TRACE_ARGIK(c,i,k) \
|
||||
xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
|
||||
xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__)
|
||||
#define XFS_BMBT_TRACE_CURSOR(c,s) \
|
||||
xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
|
||||
xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__)
|
||||
#else
|
||||
#define XFS_BMBT_TRACE_ARGBI(c,b,i)
|
||||
#define XFS_BMBT_TRACE_ARGBII(c,b,i,j)
|
||||
|
@ -318,9 +318,6 @@ xfs_bmbt_delrec(
|
|||
xfs_fsblock_t bno; /* fs-relative block number */
|
||||
xfs_buf_t *bp; /* buffer for block */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_delrec";
|
||||
#endif
|
||||
int i; /* loop counter */
|
||||
int j; /* temp state */
|
||||
xfs_bmbt_key_t key; /* bmap btree key */
|
||||
|
@ -694,9 +691,6 @@ xfs_bmbt_insrec(
|
|||
xfs_bmbt_block_t *block; /* bmap btree block */
|
||||
xfs_buf_t *bp; /* buffer for block */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_insrec";
|
||||
#endif
|
||||
int i; /* loop index */
|
||||
xfs_bmbt_key_t key; /* bmap btree key */
|
||||
xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */
|
||||
|
@ -880,9 +874,6 @@ xfs_bmbt_killroot(
|
|||
xfs_bmbt_ptr_t *cpp;
|
||||
#ifdef DEBUG
|
||||
int error;
|
||||
#endif
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_killroot";
|
||||
#endif
|
||||
int i;
|
||||
xfs_bmbt_key_t *kp;
|
||||
|
@ -973,9 +964,6 @@ xfs_bmbt_log_keys(
|
|||
int kfirst,
|
||||
int klast)
|
||||
{
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_log_keys";
|
||||
#endif
|
||||
xfs_trans_t *tp;
|
||||
|
||||
XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
|
||||
|
@ -1012,9 +1000,6 @@ xfs_bmbt_log_ptrs(
|
|||
int pfirst,
|
||||
int plast)
|
||||
{
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_log_ptrs";
|
||||
#endif
|
||||
xfs_trans_t *tp;
|
||||
|
||||
XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
|
||||
|
@ -1055,9 +1040,6 @@ xfs_bmbt_lookup(
|
|||
xfs_daddr_t d;
|
||||
xfs_sfiloff_t diff;
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_lookup";
|
||||
#endif
|
||||
xfs_fsblock_t fsbno=0;
|
||||
int high;
|
||||
int i;
|
||||
|
@ -1195,9 +1177,6 @@ xfs_bmbt_lshift(
|
|||
int *stat) /* success/failure */
|
||||
{
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_lshift";
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
int i; /* loop counter */
|
||||
#endif
|
||||
|
@ -1331,9 +1310,6 @@ xfs_bmbt_rshift(
|
|||
int *stat) /* success/failure */
|
||||
{
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_rshift";
|
||||
#endif
|
||||
int i; /* loop counter */
|
||||
xfs_bmbt_key_t key; /* bmap btree key */
|
||||
xfs_buf_t *lbp; /* left buffer pointer */
|
||||
|
@ -1492,9 +1468,6 @@ xfs_bmbt_split(
|
|||
{
|
||||
xfs_alloc_arg_t args; /* block allocation args */
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_split";
|
||||
#endif
|
||||
int i; /* loop counter */
|
||||
xfs_fsblock_t lbno; /* left sibling block number */
|
||||
xfs_buf_t *lbp; /* left buffer pointer */
|
||||
|
@ -1640,9 +1613,6 @@ xfs_bmbt_updkey(
|
|||
xfs_buf_t *bp;
|
||||
#ifdef DEBUG
|
||||
int error;
|
||||
#endif
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_updkey";
|
||||
#endif
|
||||
xfs_bmbt_key_t *kp;
|
||||
int ptr;
|
||||
|
@ -1712,9 +1682,6 @@ xfs_bmbt_decrement(
|
|||
xfs_bmbt_block_t *block;
|
||||
xfs_buf_t *bp;
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_decrement";
|
||||
#endif
|
||||
xfs_fsblock_t fsbno;
|
||||
int lev;
|
||||
xfs_mount_t *mp;
|
||||
|
@ -1785,9 +1752,6 @@ xfs_bmbt_delete(
|
|||
int *stat) /* success/failure */
|
||||
{
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_delete";
|
||||
#endif
|
||||
int i;
|
||||
int level;
|
||||
|
||||
|
@ -2000,9 +1964,6 @@ xfs_bmbt_increment(
|
|||
xfs_bmbt_block_t *block;
|
||||
xfs_buf_t *bp;
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_increment";
|
||||
#endif
|
||||
xfs_fsblock_t fsbno;
|
||||
int lev;
|
||||
xfs_mount_t *mp;
|
||||
|
@ -2080,9 +2041,6 @@ xfs_bmbt_insert(
|
|||
int *stat) /* success/failure */
|
||||
{
|
||||
int error; /* error return value */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_insert";
|
||||
#endif
|
||||
int i;
|
||||
int level;
|
||||
xfs_fsblock_t nbno;
|
||||
|
@ -2142,9 +2100,6 @@ xfs_bmbt_log_block(
|
|||
int fields)
|
||||
{
|
||||
int first;
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_log_block";
|
||||
#endif
|
||||
int last;
|
||||
xfs_trans_t *tp;
|
||||
static const short offsets[] = {
|
||||
|
@ -2181,9 +2136,6 @@ xfs_bmbt_log_recs(
|
|||
{
|
||||
xfs_bmbt_block_t *block;
|
||||
int first;
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_log_recs";
|
||||
#endif
|
||||
int last;
|
||||
xfs_bmbt_rec_t *rp;
|
||||
xfs_trans_t *tp;
|
||||
|
@ -2245,9 +2197,6 @@ xfs_bmbt_newroot(
|
|||
xfs_bmbt_key_t *ckp; /* child key pointer */
|
||||
xfs_bmbt_ptr_t *cpp; /* child ptr pointer */
|
||||
int error; /* error return code */
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_newroot";
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
int i; /* loop counter */
|
||||
#endif
|
||||
|
@ -2630,9 +2579,6 @@ xfs_bmbt_update(
|
|||
xfs_bmbt_block_t *block;
|
||||
xfs_buf_t *bp;
|
||||
int error;
|
||||
#ifdef XFS_BMBT_TRACE
|
||||
static char fname[] = "xfs_bmbt_update";
|
||||
#endif
|
||||
xfs_bmbt_key_t key;
|
||||
int ptr;
|
||||
xfs_bmbt_rec_t *rp;
|
||||
|
|
|
@ -444,30 +444,14 @@ xfs_btree_setbuf(
|
|||
/*
|
||||
* Min and max functions for extlen, agblock, fileoff, and filblks types.
|
||||
*/
|
||||
#define XFS_EXTLEN_MIN(a,b) \
|
||||
((xfs_extlen_t)(a) < (xfs_extlen_t)(b) ? \
|
||||
(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
|
||||
#define XFS_EXTLEN_MAX(a,b) \
|
||||
((xfs_extlen_t)(a) > (xfs_extlen_t)(b) ? \
|
||||
(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
|
||||
#define XFS_AGBLOCK_MIN(a,b) \
|
||||
((xfs_agblock_t)(a) < (xfs_agblock_t)(b) ? \
|
||||
(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
|
||||
#define XFS_AGBLOCK_MAX(a,b) \
|
||||
((xfs_agblock_t)(a) > (xfs_agblock_t)(b) ? \
|
||||
(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
|
||||
#define XFS_FILEOFF_MIN(a,b) \
|
||||
((xfs_fileoff_t)(a) < (xfs_fileoff_t)(b) ? \
|
||||
(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
|
||||
#define XFS_FILEOFF_MAX(a,b) \
|
||||
((xfs_fileoff_t)(a) > (xfs_fileoff_t)(b) ? \
|
||||
(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
|
||||
#define XFS_FILBLKS_MIN(a,b) \
|
||||
((xfs_filblks_t)(a) < (xfs_filblks_t)(b) ? \
|
||||
(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
|
||||
#define XFS_FILBLKS_MAX(a,b) \
|
||||
((xfs_filblks_t)(a) > (xfs_filblks_t)(b) ? \
|
||||
(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
|
||||
#define XFS_EXTLEN_MIN(a,b) min_t(xfs_extlen_t, (a), (b))
|
||||
#define XFS_EXTLEN_MAX(a,b) max_t(xfs_extlen_t, (a), (b))
|
||||
#define XFS_AGBLOCK_MIN(a,b) min_t(xfs_agblock_t, (a), (b))
|
||||
#define XFS_AGBLOCK_MAX(a,b) max_t(xfs_agblock_t, (a), (b))
|
||||
#define XFS_FILEOFF_MIN(a,b) min_t(xfs_fileoff_t, (a), (b))
|
||||
#define XFS_FILEOFF_MAX(a,b) max_t(xfs_fileoff_t, (a), (b))
|
||||
#define XFS_FILBLKS_MIN(a,b) min_t(xfs_filblks_t, (a), (b))
|
||||
#define XFS_FILBLKS_MAX(a,b) max_t(xfs_filblks_t, (a), (b))
|
||||
|
||||
#define XFS_FSB_SANITY_CHECK(mp,fsb) \
|
||||
(XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \
|
||||
|
|
|
@ -580,8 +580,8 @@ xfs_buf_item_unlock(
|
|||
* If the buf item isn't tracking any data, free it.
|
||||
* Otherwise, if XFS_BLI_HOLD is set clear it.
|
||||
*/
|
||||
if (xfs_count_bits(bip->bli_format.blf_data_map,
|
||||
bip->bli_format.blf_map_size, 0) == 0) {
|
||||
if (xfs_bitmap_empty(bip->bli_format.blf_data_map,
|
||||
bip->bli_format.blf_map_size)) {
|
||||
xfs_buf_item_relse(bp);
|
||||
} else if (hold) {
|
||||
bip->bli_flags &= ~XFS_BLI_HOLD;
|
||||
|
|
|
@ -99,5 +99,7 @@ struct xfs_mount_args {
|
|||
*/
|
||||
#define XFSMNT2_COMPAT_IOSIZE 0x00000001 /* don't report large preferred
|
||||
* I/O size in stat(2) */
|
||||
#define XFSMNT2_FILESTREAMS 0x00000002 /* enable the filestreams
|
||||
* allocator */
|
||||
|
||||
#endif /* __XFS_CLNT_H__ */
|
||||
|
|
|
@ -257,6 +257,7 @@ typedef enum xfs_dinode_fmt
|
|||
#define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */
|
||||
#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */
|
||||
#define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */
|
||||
#define XFS_DIFLAG_FILESTREAM_BIT 14 /* use filestream allocator */
|
||||
#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT)
|
||||
#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT)
|
||||
#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT)
|
||||
|
@ -271,12 +272,13 @@ typedef enum xfs_dinode_fmt
|
|||
#define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT)
|
||||
#define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
|
||||
#define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT)
|
||||
#define XFS_DIFLAG_FILESTREAM (1 << XFS_DIFLAG_FILESTREAM_BIT)
|
||||
|
||||
#define XFS_DIFLAG_ANY \
|
||||
(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
|
||||
XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
|
||||
XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
|
||||
XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
|
||||
XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG)
|
||||
XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM)
|
||||
|
||||
#endif /* __XFS_DINODE_H__ */
|
||||
|
|
|
@ -55,9 +55,9 @@ xfs_dir_mount(
|
|||
XFS_MAX_BLOCKSIZE);
|
||||
mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
|
||||
mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
|
||||
mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp));
|
||||
mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
|
||||
mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp));
|
||||
mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp));
|
||||
mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
|
||||
mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp));
|
||||
mp->m_attr_node_ents =
|
||||
(mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
|
||||
(uint)sizeof(xfs_da_node_entry_t);
|
||||
|
@ -554,7 +554,7 @@ xfs_dir2_grow_inode(
|
|||
*/
|
||||
if (mapp != &map)
|
||||
kmem_free(mapp, sizeof(*mapp) * count);
|
||||
*dbp = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)bno);
|
||||
*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
|
||||
/*
|
||||
* Update file's size if this is the data space and it grew.
|
||||
*/
|
||||
|
@ -706,7 +706,7 @@ xfs_dir2_shrink_inode(
|
|||
dp = args->dp;
|
||||
mp = dp->i_mount;
|
||||
tp = args->trans;
|
||||
da = XFS_DIR2_DB_TO_DA(mp, db);
|
||||
da = xfs_dir2_db_to_da(mp, db);
|
||||
/*
|
||||
* Unmap the fsblock(s).
|
||||
*/
|
||||
|
@ -742,7 +742,7 @@ xfs_dir2_shrink_inode(
|
|||
/*
|
||||
* If the block isn't the last one in the directory, we're done.
|
||||
*/
|
||||
if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0))
|
||||
if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0))
|
||||
return 0;
|
||||
bno = da;
|
||||
if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
|
||||
|
|
|
@ -115,13 +115,13 @@ xfs_dir2_block_addname(
|
|||
xfs_da_brelse(tp, bp);
|
||||
return XFS_ERROR(EFSCORRUPTED);
|
||||
}
|
||||
len = XFS_DIR2_DATA_ENTSIZE(args->namelen);
|
||||
len = xfs_dir2_data_entsize(args->namelen);
|
||||
/*
|
||||
* Set up pointers to parts of the block.
|
||||
*/
|
||||
bf = block->hdr.bestfree;
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
* No stale entries? Need space for entry and new leaf.
|
||||
*/
|
||||
|
@ -396,7 +396,7 @@ xfs_dir2_block_addname(
|
|||
* Fill in the leaf entry.
|
||||
*/
|
||||
blp[mid].hashval = cpu_to_be32(args->hashval);
|
||||
blp[mid].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
|
||||
blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
|
||||
(char *)dep - (char *)block));
|
||||
xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
|
||||
/*
|
||||
|
@ -411,7 +411,7 @@ xfs_dir2_block_addname(
|
|||
dep->inumber = cpu_to_be64(args->inumber);
|
||||
dep->namelen = args->namelen;
|
||||
memcpy(dep->name, args->name, args->namelen);
|
||||
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
|
||||
tagp = xfs_dir2_data_entry_tag_p(dep);
|
||||
*tagp = cpu_to_be16((char *)dep - (char *)block);
|
||||
/*
|
||||
* Clean up the bestfree array and log the header, tail, and entry.
|
||||
|
@ -455,7 +455,7 @@ xfs_dir2_block_getdents(
|
|||
/*
|
||||
* If the block number in the offset is out of range, we're done.
|
||||
*/
|
||||
if (XFS_DIR2_DATAPTR_TO_DB(mp, uio->uio_offset) > mp->m_dirdatablk) {
|
||||
if (xfs_dir2_dataptr_to_db(mp, uio->uio_offset) > mp->m_dirdatablk) {
|
||||
*eofp = 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -471,15 +471,15 @@ xfs_dir2_block_getdents(
|
|||
* Extract the byte offset we start at from the seek pointer.
|
||||
* We'll skip entries before this.
|
||||
*/
|
||||
wantoff = XFS_DIR2_DATAPTR_TO_OFF(mp, uio->uio_offset);
|
||||
wantoff = xfs_dir2_dataptr_to_off(mp, uio->uio_offset);
|
||||
block = bp->data;
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
/*
|
||||
* Set up values for the loop.
|
||||
*/
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
ptr = (char *)block->u;
|
||||
endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
endptr = (char *)xfs_dir2_block_leaf_p(btp);
|
||||
p.dbp = dbp;
|
||||
p.put = put;
|
||||
p.uio = uio;
|
||||
|
@ -502,7 +502,7 @@ xfs_dir2_block_getdents(
|
|||
/*
|
||||
* Bump pointer for the next iteration.
|
||||
*/
|
||||
ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
|
||||
ptr += xfs_dir2_data_entsize(dep->namelen);
|
||||
/*
|
||||
* The entry is before the desired starting point, skip it.
|
||||
*/
|
||||
|
@ -513,7 +513,7 @@ xfs_dir2_block_getdents(
|
|||
*/
|
||||
p.namelen = dep->namelen;
|
||||
|
||||
p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
ptr - (char *)block);
|
||||
p.ino = be64_to_cpu(dep->inumber);
|
||||
#if XFS_BIG_INUMS
|
||||
|
@ -531,7 +531,7 @@ xfs_dir2_block_getdents(
|
|||
*/
|
||||
if (!p.done) {
|
||||
uio->uio_offset =
|
||||
XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
(char *)dep - (char *)block);
|
||||
xfs_da_brelse(tp, bp);
|
||||
return error;
|
||||
|
@ -545,7 +545,7 @@ xfs_dir2_block_getdents(
|
|||
*eofp = 1;
|
||||
|
||||
uio->uio_offset =
|
||||
XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
|
||||
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
|
||||
|
||||
xfs_da_brelse(tp, bp);
|
||||
|
||||
|
@ -569,8 +569,8 @@ xfs_dir2_block_log_leaf(
|
|||
|
||||
mp = tp->t_mountp;
|
||||
block = bp->data;
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)block),
|
||||
(uint)((char *)&blp[last + 1] - (char *)block - 1));
|
||||
}
|
||||
|
@ -589,7 +589,7 @@ xfs_dir2_block_log_tail(
|
|||
|
||||
mp = tp->t_mountp;
|
||||
block = bp->data;
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)block),
|
||||
(uint)((char *)(btp + 1) - (char *)block - 1));
|
||||
}
|
||||
|
@ -623,13 +623,13 @@ xfs_dir2_block_lookup(
|
|||
mp = dp->i_mount;
|
||||
block = bp->data;
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
* Get the offset from the leaf entry, to point to the data.
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
|
||||
((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
|
||||
/*
|
||||
* Fill in inode number, release the block.
|
||||
*/
|
||||
|
@ -675,8 +675,8 @@ xfs_dir2_block_lookup_int(
|
|||
ASSERT(bp != NULL);
|
||||
block = bp->data;
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
* Loop doing a binary search for our hash value.
|
||||
* Find our entry, ENOENT if it's not there.
|
||||
|
@ -713,7 +713,7 @@ xfs_dir2_block_lookup_int(
|
|||
* Get pointer to the entry from the leaf.
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
|
||||
((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
|
||||
/*
|
||||
* Compare, if it's right give back buffer & entry number.
|
||||
*/
|
||||
|
@ -768,20 +768,20 @@ xfs_dir2_block_removename(
|
|||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
block = bp->data;
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
* Point to the data entry using the leaf entry.
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
|
||||
((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
|
||||
/*
|
||||
* Mark the data entry's space free.
|
||||
*/
|
||||
needlog = needscan = 0;
|
||||
xfs_dir2_data_make_free(tp, bp,
|
||||
(xfs_dir2_data_aoff_t)((char *)dep - (char *)block),
|
||||
XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
|
||||
xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
|
||||
/*
|
||||
* Fix up the block tail.
|
||||
*/
|
||||
|
@ -843,13 +843,13 @@ xfs_dir2_block_replace(
|
|||
dp = args->dp;
|
||||
mp = dp->i_mount;
|
||||
block = bp->data;
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
* Point to the data entry we need to change.
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
|
||||
((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
|
||||
ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
|
||||
/*
|
||||
* Change the inode number to the new value.
|
||||
|
@ -912,7 +912,7 @@ xfs_dir2_leaf_to_block(
|
|||
mp = dp->i_mount;
|
||||
leaf = lbp->data;
|
||||
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
/*
|
||||
* If there are data blocks other than the first one, take this
|
||||
* opportunity to remove trailing empty data blocks that may have
|
||||
|
@ -920,7 +920,7 @@ xfs_dir2_leaf_to_block(
|
|||
* These will show up in the leaf bests table.
|
||||
*/
|
||||
while (dp->i_d.di_size > mp->m_dirblksize) {
|
||||
bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
|
||||
bestsp = xfs_dir2_leaf_bests_p(ltp);
|
||||
if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
|
||||
mp->m_dirblksize - (uint)sizeof(block->hdr)) {
|
||||
if ((error =
|
||||
|
@ -974,14 +974,14 @@ xfs_dir2_leaf_to_block(
|
|||
/*
|
||||
* Initialize the block tail.
|
||||
*/
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
btp->count = cpu_to_be32(be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale));
|
||||
btp->stale = 0;
|
||||
xfs_dir2_block_log_tail(tp, dbp);
|
||||
/*
|
||||
* Initialize the block leaf area. We compact out stale entries.
|
||||
*/
|
||||
lep = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
lep = xfs_dir2_block_leaf_p(btp);
|
||||
for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) {
|
||||
if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)
|
||||
continue;
|
||||
|
@ -1067,7 +1067,7 @@ xfs_dir2_sf_to_block(
|
|||
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
|
||||
ASSERT(dp->i_df.if_u1.if_data != NULL);
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
|
||||
ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
|
||||
/*
|
||||
* Copy the directory into the stack buffer.
|
||||
* Then pitch the incore inode data so we can make extents.
|
||||
|
@ -1119,10 +1119,10 @@ xfs_dir2_sf_to_block(
|
|||
/*
|
||||
* Fill in the tail.
|
||||
*/
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
btp->count = cpu_to_be32(sfp->hdr.count + 2); /* ., .. */
|
||||
btp->stale = 0;
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
endoffset = (uint)((char *)blp - (char *)block);
|
||||
/*
|
||||
* Remove the freespace, we'll manage it.
|
||||
|
@ -1138,25 +1138,25 @@ xfs_dir2_sf_to_block(
|
|||
dep->inumber = cpu_to_be64(dp->i_ino);
|
||||
dep->namelen = 1;
|
||||
dep->name[0] = '.';
|
||||
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
|
||||
tagp = xfs_dir2_data_entry_tag_p(dep);
|
||||
*tagp = cpu_to_be16((char *)dep - (char *)block);
|
||||
xfs_dir2_data_log_entry(tp, bp, dep);
|
||||
blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
|
||||
blp[0].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
|
||||
blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
|
||||
(char *)dep - (char *)block));
|
||||
/*
|
||||
* Create entry for ..
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
|
||||
dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
|
||||
dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
|
||||
dep->namelen = 2;
|
||||
dep->name[0] = dep->name[1] = '.';
|
||||
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
|
||||
tagp = xfs_dir2_data_entry_tag_p(dep);
|
||||
*tagp = cpu_to_be16((char *)dep - (char *)block);
|
||||
xfs_dir2_data_log_entry(tp, bp, dep);
|
||||
blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
|
||||
blp[1].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
|
||||
blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
|
||||
(char *)dep - (char *)block));
|
||||
offset = XFS_DIR2_DATA_FIRST_OFFSET;
|
||||
/*
|
||||
|
@ -1165,7 +1165,7 @@ xfs_dir2_sf_to_block(
|
|||
if ((i = 0) == sfp->hdr.count)
|
||||
sfep = NULL;
|
||||
else
|
||||
sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
/*
|
||||
* Need to preserve the existing offset values in the sf directory.
|
||||
* Insert holes (unused entries) where necessary.
|
||||
|
@ -1177,7 +1177,7 @@ xfs_dir2_sf_to_block(
|
|||
if (sfep == NULL)
|
||||
newoffset = endoffset;
|
||||
else
|
||||
newoffset = XFS_DIR2_SF_GET_OFFSET(sfep);
|
||||
newoffset = xfs_dir2_sf_get_offset(sfep);
|
||||
/*
|
||||
* There should be a hole here, make one.
|
||||
*/
|
||||
|
@ -1186,7 +1186,7 @@ xfs_dir2_sf_to_block(
|
|||
((char *)block + offset);
|
||||
dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
|
||||
dup->length = cpu_to_be16(newoffset - offset);
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16(
|
||||
*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
|
||||
((char *)dup - (char *)block));
|
||||
xfs_dir2_data_log_unused(tp, bp, dup);
|
||||
(void)xfs_dir2_data_freeinsert((xfs_dir2_data_t *)block,
|
||||
|
@ -1198,22 +1198,22 @@ xfs_dir2_sf_to_block(
|
|||
* Copy a real entry.
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
|
||||
dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp,
|
||||
XFS_DIR2_SF_INUMBERP(sfep)));
|
||||
dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp,
|
||||
xfs_dir2_sf_inumberp(sfep)));
|
||||
dep->namelen = sfep->namelen;
|
||||
memcpy(dep->name, sfep->name, dep->namelen);
|
||||
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
|
||||
tagp = xfs_dir2_data_entry_tag_p(dep);
|
||||
*tagp = cpu_to_be16((char *)dep - (char *)block);
|
||||
xfs_dir2_data_log_entry(tp, bp, dep);
|
||||
blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname(
|
||||
(char *)sfep->name, sfep->namelen));
|
||||
blp[2 + i].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
|
||||
blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
|
||||
(char *)dep - (char *)block));
|
||||
offset = (int)((char *)(tagp + 1) - (char *)block);
|
||||
if (++i == sfp->hdr.count)
|
||||
sfep = NULL;
|
||||
else
|
||||
sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
|
||||
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
|
||||
}
|
||||
/* Done with the temporary buffer */
|
||||
kmem_free(buf, buf_len);
|
||||
|
|
|
@ -60,7 +60,6 @@ typedef struct xfs_dir2_block {
|
|||
/*
|
||||
* Pointer to the leaf header embedded in a data block (1-block format)
|
||||
*/
|
||||
#define XFS_DIR2_BLOCK_TAIL_P(mp,block) xfs_dir2_block_tail_p(mp,block)
|
||||
static inline xfs_dir2_block_tail_t *
|
||||
xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
|
||||
{
|
||||
|
@ -71,7 +70,6 @@ xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
|
|||
/*
|
||||
* Pointer to the leaf entries embedded in a data block (1-block format)
|
||||
*/
|
||||
#define XFS_DIR2_BLOCK_LEAF_P(btp) xfs_dir2_block_leaf_p(btp)
|
||||
static inline struct xfs_dir2_leaf_entry *
|
||||
xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
|
||||
{
|
||||
|
|
|
@ -72,8 +72,8 @@ xfs_dir2_data_check(
|
|||
bf = d->hdr.bestfree;
|
||||
p = (char *)d->u;
|
||||
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
|
||||
lep = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
|
||||
lep = xfs_dir2_block_leaf_p(btp);
|
||||
endp = (char *)lep;
|
||||
} else
|
||||
endp = (char *)d + mp->m_dirblksize;
|
||||
|
@ -107,7 +107,7 @@ xfs_dir2_data_check(
|
|||
*/
|
||||
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
|
||||
ASSERT(lastfree == 0);
|
||||
ASSERT(be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)) ==
|
||||
ASSERT(be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
|
||||
(char *)dup - (char *)d);
|
||||
dfp = xfs_dir2_data_freefind(d, dup);
|
||||
if (dfp) {
|
||||
|
@ -131,12 +131,12 @@ xfs_dir2_data_check(
|
|||
dep = (xfs_dir2_data_entry_t *)p;
|
||||
ASSERT(dep->namelen != 0);
|
||||
ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
|
||||
ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) ==
|
||||
ASSERT(be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
|
||||
(char *)dep - (char *)d);
|
||||
count++;
|
||||
lastfree = 0;
|
||||
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
|
||||
addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
(xfs_dir2_data_aoff_t)
|
||||
((char *)dep - (char *)d));
|
||||
hash = xfs_da_hashname((char *)dep->name, dep->namelen);
|
||||
|
@ -147,7 +147,7 @@ xfs_dir2_data_check(
|
|||
}
|
||||
ASSERT(i < be32_to_cpu(btp->count));
|
||||
}
|
||||
p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
|
||||
p += xfs_dir2_data_entsize(dep->namelen);
|
||||
}
|
||||
/*
|
||||
* Need to have seen all the entries and all the bestfree slots.
|
||||
|
@ -346,8 +346,8 @@ xfs_dir2_data_freescan(
|
|||
*/
|
||||
p = (char *)d->u;
|
||||
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
|
||||
endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
|
||||
endp = (char *)xfs_dir2_block_leaf_p(btp);
|
||||
} else
|
||||
endp = (char *)d + mp->m_dirblksize;
|
||||
/*
|
||||
|
@ -360,7 +360,7 @@ xfs_dir2_data_freescan(
|
|||
*/
|
||||
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
|
||||
ASSERT((char *)dup - (char *)d ==
|
||||
be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
|
||||
be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
|
||||
xfs_dir2_data_freeinsert(d, dup, loghead);
|
||||
p += be16_to_cpu(dup->length);
|
||||
}
|
||||
|
@ -370,8 +370,8 @@ xfs_dir2_data_freescan(
|
|||
else {
|
||||
dep = (xfs_dir2_data_entry_t *)p;
|
||||
ASSERT((char *)dep - (char *)d ==
|
||||
be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)));
|
||||
p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
|
||||
be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)));
|
||||
p += xfs_dir2_data_entsize(dep->namelen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ xfs_dir2_data_init(
|
|||
/*
|
||||
* Get the buffer set up for the block.
|
||||
*/
|
||||
error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, blkno), -1, &bp,
|
||||
error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp,
|
||||
XFS_DATA_FORK);
|
||||
if (error) {
|
||||
return error;
|
||||
|
@ -427,7 +427,7 @@ xfs_dir2_data_init(
|
|||
t=mp->m_dirblksize - (uint)sizeof(d->hdr);
|
||||
d->hdr.bestfree[0].length = cpu_to_be16(t);
|
||||
dup->length = cpu_to_be16(t);
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16((char *)dup - (char *)d);
|
||||
*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)d);
|
||||
/*
|
||||
* Log it and return it.
|
||||
*/
|
||||
|
@ -452,7 +452,7 @@ xfs_dir2_data_log_entry(
|
|||
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
|
||||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d),
|
||||
(uint)((char *)(XFS_DIR2_DATA_ENTRY_TAG_P(dep) + 1) -
|
||||
(uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
|
||||
(char *)d - 1));
|
||||
}
|
||||
|
||||
|
@ -497,8 +497,8 @@ xfs_dir2_data_log_unused(
|
|||
* Log the end (tag) of the unused entry.
|
||||
*/
|
||||
xfs_da_log_buf(tp, bp,
|
||||
(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d),
|
||||
(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d +
|
||||
(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d),
|
||||
(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d +
|
||||
sizeof(xfs_dir2_data_off_t) - 1));
|
||||
}
|
||||
|
||||
|
@ -535,8 +535,8 @@ xfs_dir2_data_make_free(
|
|||
xfs_dir2_block_tail_t *btp; /* block tail */
|
||||
|
||||
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
|
||||
endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
|
||||
endptr = (char *)xfs_dir2_block_leaf_p(btp);
|
||||
}
|
||||
/*
|
||||
* If this isn't the start of the block, then back up to
|
||||
|
@ -587,7 +587,7 @@ xfs_dir2_data_make_free(
|
|||
* Fix up the new big freespace.
|
||||
*/
|
||||
be16_add(&prevdup->length, len + be16_to_cpu(postdup->length));
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
|
||||
*xfs_dir2_data_unused_tag_p(prevdup) =
|
||||
cpu_to_be16((char *)prevdup - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, prevdup);
|
||||
if (!needscan) {
|
||||
|
@ -621,7 +621,7 @@ xfs_dir2_data_make_free(
|
|||
else if (prevdup) {
|
||||
dfp = xfs_dir2_data_freefind(d, prevdup);
|
||||
be16_add(&prevdup->length, len);
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
|
||||
*xfs_dir2_data_unused_tag_p(prevdup) =
|
||||
cpu_to_be16((char *)prevdup - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, prevdup);
|
||||
/*
|
||||
|
@ -649,7 +649,7 @@ xfs_dir2_data_make_free(
|
|||
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
|
||||
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
|
||||
newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
|
||||
*xfs_dir2_data_unused_tag_p(newdup) =
|
||||
cpu_to_be16((char *)newdup - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, newdup);
|
||||
/*
|
||||
|
@ -676,7 +676,7 @@ xfs_dir2_data_make_free(
|
|||
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
|
||||
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
|
||||
newdup->length = cpu_to_be16(len);
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
|
||||
*xfs_dir2_data_unused_tag_p(newdup) =
|
||||
cpu_to_be16((char *)newdup - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, newdup);
|
||||
(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
|
||||
|
@ -712,7 +712,7 @@ xfs_dir2_data_use_free(
|
|||
ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
|
||||
ASSERT(offset >= (char *)dup - (char *)d);
|
||||
ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d);
|
||||
ASSERT((char *)dup - (char *)d == be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
|
||||
ASSERT((char *)dup - (char *)d == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
|
||||
/*
|
||||
* Look up the entry in the bestfree table.
|
||||
*/
|
||||
|
@ -745,7 +745,7 @@ xfs_dir2_data_use_free(
|
|||
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
|
||||
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
|
||||
newdup->length = cpu_to_be16(oldlen - len);
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
|
||||
*xfs_dir2_data_unused_tag_p(newdup) =
|
||||
cpu_to_be16((char *)newdup - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, newdup);
|
||||
/*
|
||||
|
@ -772,7 +772,7 @@ xfs_dir2_data_use_free(
|
|||
else if (matchback) {
|
||||
newdup = dup;
|
||||
newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
|
||||
*xfs_dir2_data_unused_tag_p(newdup) =
|
||||
cpu_to_be16((char *)newdup - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, newdup);
|
||||
/*
|
||||
|
@ -799,13 +799,13 @@ xfs_dir2_data_use_free(
|
|||
else {
|
||||
newdup = dup;
|
||||
newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
|
||||
*xfs_dir2_data_unused_tag_p(newdup) =
|
||||
cpu_to_be16((char *)newdup - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, newdup);
|
||||
newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
|
||||
newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
|
||||
newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
|
||||
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup2) =
|
||||
*xfs_dir2_data_unused_tag_p(newdup2) =
|
||||
cpu_to_be16((char *)newdup2 - (char *)d);
|
||||
xfs_dir2_data_log_unused(tp, bp, newdup2);
|
||||
/*
|
||||
|
|
|
@ -44,7 +44,7 @@ struct xfs_trans;
|
|||
#define XFS_DIR2_DATA_SPACE 0
|
||||
#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
|
||||
#define XFS_DIR2_DATA_FIRSTDB(mp) \
|
||||
XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATA_OFFSET)
|
||||
xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
|
||||
|
||||
/*
|
||||
* Offsets of . and .. in data space (always block 0)
|
||||
|
@ -52,9 +52,9 @@ struct xfs_trans;
|
|||
#define XFS_DIR2_DATA_DOT_OFFSET \
|
||||
((xfs_dir2_data_aoff_t)sizeof(xfs_dir2_data_hdr_t))
|
||||
#define XFS_DIR2_DATA_DOTDOT_OFFSET \
|
||||
(XFS_DIR2_DATA_DOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(1))
|
||||
(XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1))
|
||||
#define XFS_DIR2_DATA_FIRST_OFFSET \
|
||||
(XFS_DIR2_DATA_DOTDOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(2))
|
||||
(XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2))
|
||||
|
||||
/*
|
||||
* Structures.
|
||||
|
@ -123,7 +123,6 @@ typedef struct xfs_dir2_data {
|
|||
/*
|
||||
* Size of a data entry.
|
||||
*/
|
||||
#define XFS_DIR2_DATA_ENTSIZE(n) xfs_dir2_data_entsize(n)
|
||||
static inline int xfs_dir2_data_entsize(int n)
|
||||
{
|
||||
return (int)roundup(offsetof(xfs_dir2_data_entry_t, name[0]) + (n) + \
|
||||
|
@ -133,19 +132,16 @@ static inline int xfs_dir2_data_entsize(int n)
|
|||
/*
|
||||
* Pointer to an entry's tag word.
|
||||
*/
|
||||
#define XFS_DIR2_DATA_ENTRY_TAG_P(dep) xfs_dir2_data_entry_tag_p(dep)
|
||||
static inline __be16 *
|
||||
xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep)
|
||||
{
|
||||
return (__be16 *)((char *)dep +
|
||||
XFS_DIR2_DATA_ENTSIZE(dep->namelen) - sizeof(__be16));
|
||||
xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
|
||||
}
|
||||
|
||||
/*
|
||||
* Pointer to a freespace's tag word.
|
||||
*/
|
||||
#define XFS_DIR2_DATA_UNUSED_TAG_P(dup) \
|
||||
xfs_dir2_data_unused_tag_p(dup)
|
||||
static inline __be16 *
|
||||
xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup)
|
||||
{
|
||||
|
|
|
@ -92,7 +92,7 @@ xfs_dir2_block_to_leaf(
|
|||
if ((error = xfs_da_grow_inode(args, &blkno))) {
|
||||
return error;
|
||||
}
|
||||
ldb = XFS_DIR2_DA_TO_DB(mp, blkno);
|
||||
ldb = xfs_dir2_da_to_db(mp, blkno);
|
||||
ASSERT(ldb == XFS_DIR2_LEAF_FIRSTDB(mp));
|
||||
/*
|
||||
* Initialize the leaf block, get a buffer for it.
|
||||
|
@ -104,8 +104,8 @@ xfs_dir2_block_to_leaf(
|
|||
leaf = lbp->data;
|
||||
block = dbp->data;
|
||||
xfs_dir2_data_check(dp, dbp);
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
* Set the counts in the leaf header.
|
||||
*/
|
||||
|
@ -137,9 +137,9 @@ xfs_dir2_block_to_leaf(
|
|||
/*
|
||||
* Set up leaf tail and bests table.
|
||||
*/
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
ltp->bestcount = cpu_to_be32(1);
|
||||
bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
|
||||
bestsp = xfs_dir2_leaf_bests_p(ltp);
|
||||
bestsp[0] = block->hdr.bestfree[0].length;
|
||||
/*
|
||||
* Log the data header and leaf bests table.
|
||||
|
@ -209,9 +209,9 @@ xfs_dir2_leaf_addname(
|
|||
*/
|
||||
index = xfs_dir2_leaf_search_hash(args, lbp);
|
||||
leaf = lbp->data;
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
|
||||
length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
bestsp = xfs_dir2_leaf_bests_p(ltp);
|
||||
length = xfs_dir2_data_entsize(args->namelen);
|
||||
/*
|
||||
* See if there are any entries with the same hash value
|
||||
* and space in their block for the new entry.
|
||||
|
@ -223,7 +223,7 @@ xfs_dir2_leaf_addname(
|
|||
index++, lep++) {
|
||||
if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
|
||||
continue;
|
||||
i = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
|
||||
i = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
|
||||
ASSERT(i < be32_to_cpu(ltp->bestcount));
|
||||
ASSERT(be16_to_cpu(bestsp[i]) != NULLDATAOFF);
|
||||
if (be16_to_cpu(bestsp[i]) >= length) {
|
||||
|
@ -378,7 +378,7 @@ xfs_dir2_leaf_addname(
|
|||
*/
|
||||
else {
|
||||
if ((error =
|
||||
xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, use_block),
|
||||
xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, use_block),
|
||||
-1, &dbp, XFS_DATA_FORK))) {
|
||||
xfs_da_brelse(tp, lbp);
|
||||
return error;
|
||||
|
@ -407,7 +407,7 @@ xfs_dir2_leaf_addname(
|
|||
dep->inumber = cpu_to_be64(args->inumber);
|
||||
dep->namelen = args->namelen;
|
||||
memcpy(dep->name, args->name, dep->namelen);
|
||||
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
|
||||
tagp = xfs_dir2_data_entry_tag_p(dep);
|
||||
*tagp = cpu_to_be16((char *)dep - (char *)data);
|
||||
/*
|
||||
* Need to scan fix up the bestfree table.
|
||||
|
@ -529,7 +529,7 @@ xfs_dir2_leaf_addname(
|
|||
* Fill in the new leaf entry.
|
||||
*/
|
||||
lep->hashval = cpu_to_be32(args->hashval);
|
||||
lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp, use_block,
|
||||
lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, use_block,
|
||||
be16_to_cpu(*tagp)));
|
||||
/*
|
||||
* Log the leaf fields and give up the buffers.
|
||||
|
@ -567,13 +567,13 @@ xfs_dir2_leaf_check(
|
|||
* Should factor in the size of the bests table as well.
|
||||
* We can deduce a value for that from di_size.
|
||||
*/
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
/*
|
||||
* Leaves and bests don't overlap.
|
||||
*/
|
||||
ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <=
|
||||
(char *)XFS_DIR2_LEAF_BESTS_P(ltp));
|
||||
(char *)xfs_dir2_leaf_bests_p(ltp));
|
||||
/*
|
||||
* Check hash value order, count stale entries.
|
||||
*/
|
||||
|
@ -815,12 +815,12 @@ xfs_dir2_leaf_getdents(
|
|||
* Inside the loop we keep the main offset value as a byte offset
|
||||
* in the directory file.
|
||||
*/
|
||||
curoff = XFS_DIR2_DATAPTR_TO_BYTE(mp, uio->uio_offset);
|
||||
curoff = xfs_dir2_dataptr_to_byte(mp, uio->uio_offset);
|
||||
/*
|
||||
* Force this conversion through db so we truncate the offset
|
||||
* down to get the start of the data block.
|
||||
*/
|
||||
map_off = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, curoff));
|
||||
map_off = xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, curoff));
|
||||
/*
|
||||
* Loop over directory entries until we reach the end offset.
|
||||
* Get more blocks and readahead as necessary.
|
||||
|
@ -870,7 +870,7 @@ xfs_dir2_leaf_getdents(
|
|||
*/
|
||||
if (1 + ra_want > map_blocks &&
|
||||
map_off <
|
||||
XFS_DIR2_BYTE_TO_DA(mp, XFS_DIR2_LEAF_OFFSET)) {
|
||||
xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) {
|
||||
/*
|
||||
* Get more bmaps, fill in after the ones
|
||||
* we already have in the table.
|
||||
|
@ -878,7 +878,7 @@ xfs_dir2_leaf_getdents(
|
|||
nmap = map_size - map_valid;
|
||||
error = xfs_bmapi(tp, dp,
|
||||
map_off,
|
||||
XFS_DIR2_BYTE_TO_DA(mp,
|
||||
xfs_dir2_byte_to_da(mp,
|
||||
XFS_DIR2_LEAF_OFFSET) - map_off,
|
||||
XFS_BMAPI_METADATA, NULL, 0,
|
||||
&map[map_valid], &nmap, NULL, NULL);
|
||||
|
@ -903,7 +903,7 @@ xfs_dir2_leaf_getdents(
|
|||
map[map_valid + nmap - 1].br_blockcount;
|
||||
else
|
||||
map_off =
|
||||
XFS_DIR2_BYTE_TO_DA(mp,
|
||||
xfs_dir2_byte_to_da(mp,
|
||||
XFS_DIR2_LEAF_OFFSET);
|
||||
/*
|
||||
* Look for holes in the mapping, and
|
||||
|
@ -931,14 +931,14 @@ xfs_dir2_leaf_getdents(
|
|||
* No valid mappings, so no more data blocks.
|
||||
*/
|
||||
if (!map_valid) {
|
||||
curoff = XFS_DIR2_DA_TO_BYTE(mp, map_off);
|
||||
curoff = xfs_dir2_da_to_byte(mp, map_off);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Read the directory block starting at the first
|
||||
* mapping.
|
||||
*/
|
||||
curdb = XFS_DIR2_DA_TO_DB(mp, map->br_startoff);
|
||||
curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
|
||||
error = xfs_da_read_buf(tp, dp, map->br_startoff,
|
||||
map->br_blockcount >= mp->m_dirblkfsbs ?
|
||||
XFS_FSB_TO_DADDR(mp, map->br_startblock) :
|
||||
|
@ -1014,7 +1014,7 @@ xfs_dir2_leaf_getdents(
|
|||
/*
|
||||
* Having done a read, we need to set a new offset.
|
||||
*/
|
||||
newoff = XFS_DIR2_DB_OFF_TO_BYTE(mp, curdb, 0);
|
||||
newoff = xfs_dir2_db_off_to_byte(mp, curdb, 0);
|
||||
/*
|
||||
* Start of the current block.
|
||||
*/
|
||||
|
@ -1024,7 +1024,7 @@ xfs_dir2_leaf_getdents(
|
|||
* Make sure we're in the right block.
|
||||
*/
|
||||
else if (curoff > newoff)
|
||||
ASSERT(XFS_DIR2_BYTE_TO_DB(mp, curoff) ==
|
||||
ASSERT(xfs_dir2_byte_to_db(mp, curoff) ==
|
||||
curdb);
|
||||
data = bp->data;
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
|
@ -1032,7 +1032,7 @@ xfs_dir2_leaf_getdents(
|
|||
* Find our position in the block.
|
||||
*/
|
||||
ptr = (char *)&data->u;
|
||||
byteoff = XFS_DIR2_BYTE_TO_OFF(mp, curoff);
|
||||
byteoff = xfs_dir2_byte_to_off(mp, curoff);
|
||||
/*
|
||||
* Skip past the header.
|
||||
*/
|
||||
|
@ -1054,15 +1054,15 @@ xfs_dir2_leaf_getdents(
|
|||
}
|
||||
dep = (xfs_dir2_data_entry_t *)ptr;
|
||||
length =
|
||||
XFS_DIR2_DATA_ENTSIZE(dep->namelen);
|
||||
xfs_dir2_data_entsize(dep->namelen);
|
||||
ptr += length;
|
||||
}
|
||||
/*
|
||||
* Now set our real offset.
|
||||
*/
|
||||
curoff =
|
||||
XFS_DIR2_DB_OFF_TO_BYTE(mp,
|
||||
XFS_DIR2_BYTE_TO_DB(mp, curoff),
|
||||
xfs_dir2_db_off_to_byte(mp,
|
||||
xfs_dir2_byte_to_db(mp, curoff),
|
||||
(char *)ptr - (char *)data);
|
||||
if (ptr >= (char *)data + mp->m_dirblksize) {
|
||||
continue;
|
||||
|
@ -1091,9 +1091,9 @@ xfs_dir2_leaf_getdents(
|
|||
|
||||
p->namelen = dep->namelen;
|
||||
|
||||
length = XFS_DIR2_DATA_ENTSIZE(p->namelen);
|
||||
length = xfs_dir2_data_entsize(p->namelen);
|
||||
|
||||
p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
|
||||
p->cook = xfs_dir2_byte_to_dataptr(mp, curoff + length);
|
||||
|
||||
p->ino = be64_to_cpu(dep->inumber);
|
||||
#if XFS_BIG_INUMS
|
||||
|
@ -1121,10 +1121,10 @@ xfs_dir2_leaf_getdents(
|
|||
* All done. Set output offset value to current offset.
|
||||
*/
|
||||
*eofp = eof;
|
||||
if (curoff > XFS_DIR2_DATAPTR_TO_BYTE(mp, XFS_DIR2_MAX_DATAPTR))
|
||||
if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
|
||||
uio->uio_offset = XFS_DIR2_MAX_DATAPTR;
|
||||
else
|
||||
uio->uio_offset = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff);
|
||||
uio->uio_offset = xfs_dir2_byte_to_dataptr(mp, curoff);
|
||||
kmem_free(map, map_size * sizeof(*map));
|
||||
kmem_free(p, sizeof(*p));
|
||||
if (bp)
|
||||
|
@ -1159,7 +1159,7 @@ xfs_dir2_leaf_init(
|
|||
/*
|
||||
* Get the buffer for the block.
|
||||
*/
|
||||
error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, bno), -1, &bp,
|
||||
error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp,
|
||||
XFS_DATA_FORK);
|
||||
if (error) {
|
||||
return error;
|
||||
|
@ -1181,7 +1181,7 @@ xfs_dir2_leaf_init(
|
|||
* the block.
|
||||
*/
|
||||
if (magic == XFS_DIR2_LEAF1_MAGIC) {
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
ltp->bestcount = 0;
|
||||
xfs_dir2_leaf_log_tail(tp, bp);
|
||||
}
|
||||
|
@ -1206,9 +1206,9 @@ xfs_dir2_leaf_log_bests(
|
|||
|
||||
leaf = bp->data;
|
||||
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(tp->t_mountp, leaf);
|
||||
firstb = XFS_DIR2_LEAF_BESTS_P(ltp) + first;
|
||||
lastb = XFS_DIR2_LEAF_BESTS_P(ltp) + last;
|
||||
ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf);
|
||||
firstb = xfs_dir2_leaf_bests_p(ltp) + first;
|
||||
lastb = xfs_dir2_leaf_bests_p(ltp) + last;
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf),
|
||||
(uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1));
|
||||
}
|
||||
|
@ -1268,7 +1268,7 @@ xfs_dir2_leaf_log_tail(
|
|||
mp = tp->t_mountp;
|
||||
leaf = bp->data;
|
||||
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf),
|
||||
(uint)(mp->m_dirblksize - 1));
|
||||
}
|
||||
|
@ -1312,7 +1312,7 @@ xfs_dir2_leaf_lookup(
|
|||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)dbp->data +
|
||||
XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
|
||||
xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
|
||||
/*
|
||||
* Return the found inode number.
|
||||
*/
|
||||
|
@ -1381,7 +1381,7 @@ xfs_dir2_leaf_lookup_int(
|
|||
/*
|
||||
* Get the new data block number.
|
||||
*/
|
||||
newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
|
||||
newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
|
||||
/*
|
||||
* If it's not the same as the old data block number,
|
||||
* need to pitch the old one and read the new one.
|
||||
|
@ -1391,7 +1391,7 @@ xfs_dir2_leaf_lookup_int(
|
|||
xfs_da_brelse(tp, dbp);
|
||||
if ((error =
|
||||
xfs_da_read_buf(tp, dp,
|
||||
XFS_DIR2_DB_TO_DA(mp, newdb), -1, &dbp,
|
||||
xfs_dir2_db_to_da(mp, newdb), -1, &dbp,
|
||||
XFS_DATA_FORK))) {
|
||||
xfs_da_brelse(tp, lbp);
|
||||
return error;
|
||||
|
@ -1404,7 +1404,7 @@ xfs_dir2_leaf_lookup_int(
|
|||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)dbp->data +
|
||||
XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
|
||||
xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
|
||||
/*
|
||||
* If it matches then return it.
|
||||
*/
|
||||
|
@ -1469,20 +1469,20 @@ xfs_dir2_leaf_removename(
|
|||
* Point to the leaf entry, use that to point to the data entry.
|
||||
*/
|
||||
lep = &leaf->ents[index];
|
||||
db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
|
||||
db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)data + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
|
||||
((char *)data + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
|
||||
needscan = needlog = 0;
|
||||
oldbest = be16_to_cpu(data->hdr.bestfree[0].length);
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
bestsp = xfs_dir2_leaf_bests_p(ltp);
|
||||
ASSERT(be16_to_cpu(bestsp[db]) == oldbest);
|
||||
/*
|
||||
* Mark the former data entry unused.
|
||||
*/
|
||||
xfs_dir2_data_make_free(tp, dbp,
|
||||
(xfs_dir2_data_aoff_t)((char *)dep - (char *)data),
|
||||
XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
|
||||
xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
|
||||
/*
|
||||
* We just mark the leaf entry stale by putting a null in it.
|
||||
*/
|
||||
|
@ -1602,7 +1602,7 @@ xfs_dir2_leaf_replace(
|
|||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)dbp->data +
|
||||
XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
|
||||
xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
|
||||
ASSERT(args->inumber != be64_to_cpu(dep->inumber));
|
||||
/*
|
||||
* Put the new inode number in, log it.
|
||||
|
@ -1698,7 +1698,7 @@ xfs_dir2_leaf_trim_data(
|
|||
/*
|
||||
* Read the offending data block. We need its buffer.
|
||||
*/
|
||||
if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, db), -1, &dbp,
|
||||
if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp,
|
||||
XFS_DATA_FORK))) {
|
||||
return error;
|
||||
}
|
||||
|
@ -1712,7 +1712,7 @@ xfs_dir2_leaf_trim_data(
|
|||
*/
|
||||
|
||||
leaf = lbp->data;
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) ==
|
||||
mp->m_dirblksize - (uint)sizeof(data->hdr));
|
||||
ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
|
||||
|
@ -1727,7 +1727,7 @@ xfs_dir2_leaf_trim_data(
|
|||
/*
|
||||
* Eliminate the last bests entry from the table.
|
||||
*/
|
||||
bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
|
||||
bestsp = xfs_dir2_leaf_bests_p(ltp);
|
||||
be32_add(<p->bestcount, -1);
|
||||
memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp));
|
||||
xfs_dir2_leaf_log_tail(tp, lbp);
|
||||
|
@ -1838,12 +1838,12 @@ xfs_dir2_node_to_leaf(
|
|||
/*
|
||||
* Set up the leaf tail from the freespace block.
|
||||
*/
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
ltp->bestcount = free->hdr.nvalid;
|
||||
/*
|
||||
* Set up the leaf bests table.
|
||||
*/
|
||||
memcpy(XFS_DIR2_LEAF_BESTS_P(ltp), free->bests,
|
||||
memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests,
|
||||
be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0]));
|
||||
xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
|
||||
xfs_dir2_leaf_log_tail(tp, lbp);
|
||||
|
|
|
@ -32,7 +32,7 @@ struct xfs_trans;
|
|||
#define XFS_DIR2_LEAF_SPACE 1
|
||||
#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
|
||||
#define XFS_DIR2_LEAF_FIRSTDB(mp) \
|
||||
XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_LEAF_OFFSET)
|
||||
xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
|
||||
|
||||
/*
|
||||
* Offset in data space of a data entry.
|
||||
|
@ -82,7 +82,6 @@ typedef struct xfs_dir2_leaf {
|
|||
* DB blocks here are logical directory block numbers, not filesystem blocks.
|
||||
*/
|
||||
|
||||
#define XFS_DIR2_MAX_LEAF_ENTS(mp) xfs_dir2_max_leaf_ents(mp)
|
||||
static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
|
||||
{
|
||||
return (int)(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_leaf_hdr_t)) /
|
||||
|
@ -92,7 +91,6 @@ static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
|
|||
/*
|
||||
* Get address of the bestcount field in the single-leaf block.
|
||||
*/
|
||||
#define XFS_DIR2_LEAF_TAIL_P(mp,lp) xfs_dir2_leaf_tail_p(mp, lp)
|
||||
static inline xfs_dir2_leaf_tail_t *
|
||||
xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
|
||||
{
|
||||
|
@ -104,7 +102,6 @@ xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
|
|||
/*
|
||||
* Get address of the bests array in the single-leaf block.
|
||||
*/
|
||||
#define XFS_DIR2_LEAF_BESTS_P(ltp) xfs_dir2_leaf_bests_p(ltp)
|
||||
static inline __be16 *
|
||||
xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
|
||||
{
|
||||
|
@ -114,7 +111,6 @@ xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
|
|||
/*
|
||||
* Convert dataptr to byte in file space
|
||||
*/
|
||||
#define XFS_DIR2_DATAPTR_TO_BYTE(mp,dp) xfs_dir2_dataptr_to_byte(mp, dp)
|
||||
static inline xfs_dir2_off_t
|
||||
xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
|
||||
{
|
||||
|
@ -124,7 +120,6 @@ xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
|
|||
/*
|
||||
* Convert byte in file space to dataptr. It had better be aligned.
|
||||
*/
|
||||
#define XFS_DIR2_BYTE_TO_DATAPTR(mp,by) xfs_dir2_byte_to_dataptr(mp,by)
|
||||
static inline xfs_dir2_dataptr_t
|
||||
xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
|
||||
{
|
||||
|
@ -134,7 +129,6 @@ xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
|
|||
/*
|
||||
* Convert byte in space to (DB) block
|
||||
*/
|
||||
#define XFS_DIR2_BYTE_TO_DB(mp,by) xfs_dir2_byte_to_db(mp, by)
|
||||
static inline xfs_dir2_db_t
|
||||
xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
|
||||
{
|
||||
|
@ -145,17 +139,15 @@ xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
|
|||
/*
|
||||
* Convert dataptr to a block number
|
||||
*/
|
||||
#define XFS_DIR2_DATAPTR_TO_DB(mp,dp) xfs_dir2_dataptr_to_db(mp, dp)
|
||||
static inline xfs_dir2_db_t
|
||||
xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
|
||||
{
|
||||
return XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
|
||||
return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert byte in space to offset in a block
|
||||
*/
|
||||
#define XFS_DIR2_BYTE_TO_OFF(mp,by) xfs_dir2_byte_to_off(mp, by)
|
||||
static inline xfs_dir2_data_aoff_t
|
||||
xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
|
||||
{
|
||||
|
@ -166,18 +158,15 @@ xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
|
|||
/*
|
||||
* Convert dataptr to a byte offset in a block
|
||||
*/
|
||||
#define XFS_DIR2_DATAPTR_TO_OFF(mp,dp) xfs_dir2_dataptr_to_off(mp, dp)
|
||||
static inline xfs_dir2_data_aoff_t
|
||||
xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
|
||||
{
|
||||
return XFS_DIR2_BYTE_TO_OFF(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
|
||||
return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert block and offset to byte in space
|
||||
*/
|
||||
#define XFS_DIR2_DB_OFF_TO_BYTE(mp,db,o) \
|
||||
xfs_dir2_db_off_to_byte(mp, db, o)
|
||||
static inline xfs_dir2_off_t
|
||||
xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
|
||||
xfs_dir2_data_aoff_t o)
|
||||
|
@ -189,7 +178,6 @@ xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
|
|||
/*
|
||||
* Convert block (DB) to block (dablk)
|
||||
*/
|
||||
#define XFS_DIR2_DB_TO_DA(mp,db) xfs_dir2_db_to_da(mp, db)
|
||||
static inline xfs_dablk_t
|
||||
xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
|
||||
{
|
||||
|
@ -199,29 +187,25 @@ xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
|
|||
/*
|
||||
* Convert byte in space to (DA) block
|
||||
*/
|
||||
#define XFS_DIR2_BYTE_TO_DA(mp,by) xfs_dir2_byte_to_da(mp, by)
|
||||
static inline xfs_dablk_t
|
||||
xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
|
||||
{
|
||||
return XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, by));
|
||||
return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert block and offset to dataptr
|
||||
*/
|
||||
#define XFS_DIR2_DB_OFF_TO_DATAPTR(mp,db,o) \
|
||||
xfs_dir2_db_off_to_dataptr(mp, db, o)
|
||||
static inline xfs_dir2_dataptr_t
|
||||
xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
|
||||
xfs_dir2_data_aoff_t o)
|
||||
{
|
||||
return XFS_DIR2_BYTE_TO_DATAPTR(mp, XFS_DIR2_DB_OFF_TO_BYTE(mp, db, o));
|
||||
return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert block (dablk) to block (DB)
|
||||
*/
|
||||
#define XFS_DIR2_DA_TO_DB(mp,da) xfs_dir2_da_to_db(mp, da)
|
||||
static inline xfs_dir2_db_t
|
||||
xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
|
||||
{
|
||||
|
@ -231,11 +215,10 @@ xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
|
|||
/*
|
||||
* Convert block (dablk) to byte offset in space
|
||||
*/
|
||||
#define XFS_DIR2_DA_TO_BYTE(mp,da) xfs_dir2_da_to_byte(mp, da)
|
||||
static inline xfs_dir2_off_t
|
||||
xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
|
||||
{
|
||||
return XFS_DIR2_DB_OFF_TO_BYTE(mp, XFS_DIR2_DA_TO_DB(mp, da), 0);
|
||||
return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -136,14 +136,14 @@ xfs_dir2_leaf_to_node(
|
|||
/*
|
||||
* Get the buffer for the new freespace block.
|
||||
*/
|
||||
if ((error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb), -1, &fbp,
|
||||
if ((error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
|
||||
XFS_DATA_FORK))) {
|
||||
return error;
|
||||
}
|
||||
ASSERT(fbp != NULL);
|
||||
free = fbp->data;
|
||||
leaf = lbp->data;
|
||||
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
/*
|
||||
* Initialize the freespace block header.
|
||||
*/
|
||||
|
@ -155,7 +155,7 @@ xfs_dir2_leaf_to_node(
|
|||
* Copy freespace entries from the leaf block to the new block.
|
||||
* Count active entries.
|
||||
*/
|
||||
for (i = n = 0, from = XFS_DIR2_LEAF_BESTS_P(ltp), to = free->bests;
|
||||
for (i = n = 0, from = xfs_dir2_leaf_bests_p(ltp), to = free->bests;
|
||||
i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
|
||||
if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
|
||||
n++;
|
||||
|
@ -215,7 +215,7 @@ xfs_dir2_leafn_add(
|
|||
* a compact.
|
||||
*/
|
||||
|
||||
if (be16_to_cpu(leaf->hdr.count) == XFS_DIR2_MAX_LEAF_ENTS(mp)) {
|
||||
if (be16_to_cpu(leaf->hdr.count) == xfs_dir2_max_leaf_ents(mp)) {
|
||||
if (!leaf->hdr.stale)
|
||||
return XFS_ERROR(ENOSPC);
|
||||
compact = be16_to_cpu(leaf->hdr.stale) > 1;
|
||||
|
@ -327,7 +327,7 @@ xfs_dir2_leafn_add(
|
|||
* Insert the new entry, log everything.
|
||||
*/
|
||||
lep->hashval = cpu_to_be32(args->hashval);
|
||||
lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp,
|
||||
lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp,
|
||||
args->blkno, args->index));
|
||||
xfs_dir2_leaf_log_header(tp, bp);
|
||||
xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh);
|
||||
|
@ -352,7 +352,7 @@ xfs_dir2_leafn_check(
|
|||
leaf = bp->data;
|
||||
mp = dp->i_mount;
|
||||
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
|
||||
for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
|
||||
if (i + 1 < be16_to_cpu(leaf->hdr.count)) {
|
||||
ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
|
||||
|
@ -440,7 +440,7 @@ xfs_dir2_leafn_lookup_int(
|
|||
if (args->addname) {
|
||||
curfdb = curbp ? state->extrablk.blkno : -1;
|
||||
curdb = -1;
|
||||
length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
|
||||
length = xfs_dir2_data_entsize(args->namelen);
|
||||
if ((free = (curbp ? curbp->data : NULL)))
|
||||
ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
|
||||
}
|
||||
|
@ -465,7 +465,7 @@ xfs_dir2_leafn_lookup_int(
|
|||
/*
|
||||
* Pull the data block number from the entry.
|
||||
*/
|
||||
newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
|
||||
newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
|
||||
/*
|
||||
* For addname, we're looking for a place to put the new entry.
|
||||
* We want to use a data block with an entry of equal
|
||||
|
@ -482,7 +482,7 @@ xfs_dir2_leafn_lookup_int(
|
|||
* Convert the data block to the free block
|
||||
* holding its freespace information.
|
||||
*/
|
||||
newfdb = XFS_DIR2_DB_TO_FDB(mp, newdb);
|
||||
newfdb = xfs_dir2_db_to_fdb(mp, newdb);
|
||||
/*
|
||||
* If it's not the one we have in hand,
|
||||
* read it in.
|
||||
|
@ -497,7 +497,7 @@ xfs_dir2_leafn_lookup_int(
|
|||
* Read the free block.
|
||||
*/
|
||||
if ((error = xfs_da_read_buf(tp, dp,
|
||||
XFS_DIR2_DB_TO_DA(mp,
|
||||
xfs_dir2_db_to_da(mp,
|
||||
newfdb),
|
||||
-1, &curbp,
|
||||
XFS_DATA_FORK))) {
|
||||
|
@ -517,7 +517,7 @@ xfs_dir2_leafn_lookup_int(
|
|||
/*
|
||||
* Get the index for our entry.
|
||||
*/
|
||||
fi = XFS_DIR2_DB_TO_FDINDEX(mp, curdb);
|
||||
fi = xfs_dir2_db_to_fdindex(mp, curdb);
|
||||
/*
|
||||
* If it has room, return it.
|
||||
*/
|
||||
|
@ -561,7 +561,7 @@ xfs_dir2_leafn_lookup_int(
|
|||
*/
|
||||
if ((error =
|
||||
xfs_da_read_buf(tp, dp,
|
||||
XFS_DIR2_DB_TO_DA(mp, newdb), -1,
|
||||
xfs_dir2_db_to_da(mp, newdb), -1,
|
||||
&curbp, XFS_DATA_FORK))) {
|
||||
return error;
|
||||
}
|
||||
|
@ -573,7 +573,7 @@ xfs_dir2_leafn_lookup_int(
|
|||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)curbp->data +
|
||||
XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
|
||||
xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
|
||||
/*
|
||||
* Compare the entry, return it if it matches.
|
||||
*/
|
||||
|
@ -876,9 +876,9 @@ xfs_dir2_leafn_remove(
|
|||
/*
|
||||
* Extract the data block and offset from the entry.
|
||||
*/
|
||||
db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
|
||||
db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
|
||||
ASSERT(dblk->blkno == db);
|
||||
off = XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address));
|
||||
off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address));
|
||||
ASSERT(dblk->index == off);
|
||||
/*
|
||||
* Kill the leaf entry by marking it stale.
|
||||
|
@ -898,7 +898,7 @@ xfs_dir2_leafn_remove(
|
|||
longest = be16_to_cpu(data->hdr.bestfree[0].length);
|
||||
needlog = needscan = 0;
|
||||
xfs_dir2_data_make_free(tp, dbp, off,
|
||||
XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
|
||||
xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
|
||||
/*
|
||||
* Rescan the data block freespaces for bestfree.
|
||||
* Log the data block header if needed.
|
||||
|
@ -924,8 +924,8 @@ xfs_dir2_leafn_remove(
|
|||
* Convert the data block number to a free block,
|
||||
* read in the free block.
|
||||
*/
|
||||
fdb = XFS_DIR2_DB_TO_FDB(mp, db);
|
||||
if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb),
|
||||
fdb = xfs_dir2_db_to_fdb(mp, db);
|
||||
if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb),
|
||||
-1, &fbp, XFS_DATA_FORK))) {
|
||||
return error;
|
||||
}
|
||||
|
@ -937,7 +937,7 @@ xfs_dir2_leafn_remove(
|
|||
/*
|
||||
* Calculate which entry we need to fix.
|
||||
*/
|
||||
findex = XFS_DIR2_DB_TO_FDINDEX(mp, db);
|
||||
findex = xfs_dir2_db_to_fdindex(mp, db);
|
||||
longest = be16_to_cpu(data->hdr.bestfree[0].length);
|
||||
/*
|
||||
* If the data block is now empty we can get rid of it
|
||||
|
@ -1073,7 +1073,7 @@ xfs_dir2_leafn_split(
|
|||
/*
|
||||
* Initialize the new leaf block.
|
||||
*/
|
||||
error = xfs_dir2_leaf_init(args, XFS_DIR2_DA_TO_DB(mp, blkno),
|
||||
error = xfs_dir2_leaf_init(args, xfs_dir2_da_to_db(mp, blkno),
|
||||
&newblk->bp, XFS_DIR2_LEAFN_MAGIC);
|
||||
if (error) {
|
||||
return error;
|
||||
|
@ -1385,7 +1385,7 @@ xfs_dir2_node_addname_int(
|
|||
dp = args->dp;
|
||||
mp = dp->i_mount;
|
||||
tp = args->trans;
|
||||
length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
|
||||
length = xfs_dir2_data_entsize(args->namelen);
|
||||
/*
|
||||
* If we came in with a freespace block that means that lookup
|
||||
* found an entry with our hash value. This is the freespace
|
||||
|
@ -1438,7 +1438,7 @@ xfs_dir2_node_addname_int(
|
|||
|
||||
if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK)))
|
||||
return error;
|
||||
lastfbno = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo);
|
||||
lastfbno = xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo);
|
||||
fbno = ifbno;
|
||||
}
|
||||
/*
|
||||
|
@ -1474,7 +1474,7 @@ xfs_dir2_node_addname_int(
|
|||
* to avoid it.
|
||||
*/
|
||||
if ((error = xfs_da_read_buf(tp, dp,
|
||||
XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
|
||||
xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
|
||||
XFS_DATA_FORK))) {
|
||||
return error;
|
||||
}
|
||||
|
@ -1550,9 +1550,9 @@ xfs_dir2_node_addname_int(
|
|||
* Get the freespace block corresponding to the data block
|
||||
* that was just allocated.
|
||||
*/
|
||||
fbno = XFS_DIR2_DB_TO_FDB(mp, dbno);
|
||||
fbno = xfs_dir2_db_to_fdb(mp, dbno);
|
||||
if (unlikely(error = xfs_da_read_buf(tp, dp,
|
||||
XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
|
||||
xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
|
||||
XFS_DATA_FORK))) {
|
||||
xfs_da_buf_done(dbp);
|
||||
return error;
|
||||
|
@ -1567,14 +1567,14 @@ xfs_dir2_node_addname_int(
|
|||
return error;
|
||||
}
|
||||
|
||||
if (unlikely(XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno)) {
|
||||
if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
|
||||
cmn_err(CE_ALERT,
|
||||
"xfs_dir2_node_addname_int: dir ino "
|
||||
"%llu needed freesp block %lld for\n"
|
||||
" data block %lld, got %lld\n"
|
||||
" ifbno %llu lastfbno %d\n",
|
||||
(unsigned long long)dp->i_ino,
|
||||
(long long)XFS_DIR2_DB_TO_FDB(mp, dbno),
|
||||
(long long)xfs_dir2_db_to_fdb(mp, dbno),
|
||||
(long long)dbno, (long long)fbno,
|
||||
(unsigned long long)ifbno, lastfbno);
|
||||
if (fblk) {
|
||||
|
@ -1598,7 +1598,7 @@ xfs_dir2_node_addname_int(
|
|||
* Get a buffer for the new block.
|
||||
*/
|
||||
if ((error = xfs_da_get_buf(tp, dp,
|
||||
XFS_DIR2_DB_TO_DA(mp, fbno),
|
||||
xfs_dir2_db_to_da(mp, fbno),
|
||||
-1, &fbp, XFS_DATA_FORK))) {
|
||||
return error;
|
||||
}
|
||||
|
@ -1623,7 +1623,7 @@ xfs_dir2_node_addname_int(
|
|||
/*
|
||||
* Set the freespace block index from the data block number.
|
||||
*/
|
||||
findex = XFS_DIR2_DB_TO_FDINDEX(mp, dbno);
|
||||
findex = xfs_dir2_db_to_fdindex(mp, dbno);
|
||||
/*
|
||||
* If it's after the end of the current entries in the
|
||||
* freespace block, extend that table.
|
||||
|
@ -1669,7 +1669,7 @@ xfs_dir2_node_addname_int(
|
|||
* Read the data block in.
|
||||
*/
|
||||
if (unlikely(
|
||||
error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno),
|
||||
error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
|
||||
-1, &dbp, XFS_DATA_FORK))) {
|
||||
if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
|
||||
xfs_da_buf_done(fbp);
|
||||
|
@ -1698,7 +1698,7 @@ xfs_dir2_node_addname_int(
|
|||
dep->inumber = cpu_to_be64(args->inumber);
|
||||
dep->namelen = args->namelen;
|
||||
memcpy(dep->name, args->name, dep->namelen);
|
||||
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
|
||||
tagp = xfs_dir2_data_entry_tag_p(dep);
|
||||
*tagp = cpu_to_be16((char *)dep - (char *)data);
|
||||
xfs_dir2_data_log_entry(tp, dbp, dep);
|
||||
/*
|
||||
|
@ -1904,7 +1904,7 @@ xfs_dir2_node_replace(
|
|||
ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)data +
|
||||
XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address)));
|
||||
xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address)));
|
||||
ASSERT(inum != be64_to_cpu(dep->inumber));
|
||||
/*
|
||||
* Fill in the new inode number and log the entry.
|
||||
|
@ -1980,7 +1980,7 @@ xfs_dir2_node_trim_free(
|
|||
* Blow the block away.
|
||||
*/
|
||||
if ((error =
|
||||
xfs_dir2_shrink_inode(args, XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo),
|
||||
xfs_dir2_shrink_inode(args, xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo),
|
||||
bp))) {
|
||||
/*
|
||||
* Can't fail with ENOSPC since that only happens with no
|
||||
|
|
|
@ -36,7 +36,7 @@ struct xfs_trans;
|
|||
#define XFS_DIR2_FREE_SPACE 2
|
||||
#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
|
||||
#define XFS_DIR2_FREE_FIRSTDB(mp) \
|
||||
XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_FREE_OFFSET)
|
||||
xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
|
||||
|
||||
#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F */
|
||||
|
||||
|
@ -60,7 +60,6 @@ typedef struct xfs_dir2_free {
|
|||
/*
|
||||
* Convert data space db to the corresponding free db.
|
||||
*/
|
||||
#define XFS_DIR2_DB_TO_FDB(mp,db) xfs_dir2_db_to_fdb(mp, db)
|
||||
static inline xfs_dir2_db_t
|
||||
xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
|
||||
{
|
||||
|
@ -70,7 +69,6 @@ xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
|
|||
/*
|
||||
* Convert data space db to the corresponding index in a free db.
|
||||
*/
|
||||
#define XFS_DIR2_DB_TO_FDINDEX(mp,db) xfs_dir2_db_to_fdindex(mp, db)
|
||||
static inline int
|
||||
xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
|
||||
{
|
||||
|
|
|
@ -89,8 +89,8 @@ xfs_dir2_block_sfsize(
|
|||
mp = dp->i_mount;
|
||||
|
||||
count = i8count = namelen = 0;
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
blp = XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
|
||||
/*
|
||||
* Iterate over the block's data entries by using the leaf pointers.
|
||||
|
@ -102,7 +102,7 @@ xfs_dir2_block_sfsize(
|
|||
* Calculate the pointer to the entry at hand.
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
|
||||
((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
|
||||
/*
|
||||
* Detect . and .., so we can special-case them.
|
||||
* . is not included in sf directories.
|
||||
|
@ -124,7 +124,7 @@ xfs_dir2_block_sfsize(
|
|||
/*
|
||||
* Calculate the new size, see if we should give up yet.
|
||||
*/
|
||||
size = XFS_DIR2_SF_HDR_SIZE(i8count) + /* header */
|
||||
size = xfs_dir2_sf_hdr_size(i8count) + /* header */
|
||||
count + /* namelen */
|
||||
count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
|
||||
namelen + /* name */
|
||||
|
@ -139,7 +139,7 @@ xfs_dir2_block_sfsize(
|
|||
*/
|
||||
sfhp->count = count;
|
||||
sfhp->i8count = i8count;
|
||||
XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
|
||||
xfs_dir2_sf_put_inumber((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -199,15 +199,15 @@ xfs_dir2_block_to_sf(
|
|||
* Copy the header into the newly allocate local space.
|
||||
*/
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
memcpy(sfp, sfhp, XFS_DIR2_SF_HDR_SIZE(sfhp->i8count));
|
||||
memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
|
||||
dp->i_d.di_size = size;
|
||||
/*
|
||||
* Set up to loop over the block's entries.
|
||||
*/
|
||||
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
|
||||
btp = xfs_dir2_block_tail_p(mp, block);
|
||||
ptr = (char *)block->u;
|
||||
endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
|
||||
sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
endptr = (char *)xfs_dir2_block_leaf_p(btp);
|
||||
sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
/*
|
||||
* Loop over the active and unused entries.
|
||||
* Stop when we reach the leaf/tail portion of the block.
|
||||
|
@ -233,22 +233,22 @@ xfs_dir2_block_to_sf(
|
|||
else if (dep->namelen == 2 &&
|
||||
dep->name[0] == '.' && dep->name[1] == '.')
|
||||
ASSERT(be64_to_cpu(dep->inumber) ==
|
||||
XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
|
||||
xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
|
||||
/*
|
||||
* Normal entry, copy it into shortform.
|
||||
*/
|
||||
else {
|
||||
sfep->namelen = dep->namelen;
|
||||
XFS_DIR2_SF_PUT_OFFSET(sfep,
|
||||
xfs_dir2_sf_put_offset(sfep,
|
||||
(xfs_dir2_data_aoff_t)
|
||||
((char *)dep - (char *)block));
|
||||
memcpy(sfep->name, dep->name, dep->namelen);
|
||||
temp = be64_to_cpu(dep->inumber);
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
|
||||
XFS_DIR2_SF_INUMBERP(sfep));
|
||||
sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
|
||||
xfs_dir2_sf_put_inumber(sfp, &temp,
|
||||
xfs_dir2_sf_inumberp(sfep));
|
||||
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
|
||||
}
|
||||
ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
|
||||
ptr += xfs_dir2_data_entsize(dep->namelen);
|
||||
}
|
||||
ASSERT((char *)sfep - (char *)sfp == size);
|
||||
xfs_dir2_sf_check(args);
|
||||
|
@ -294,11 +294,11 @@ xfs_dir2_sf_addname(
|
|||
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
|
||||
ASSERT(dp->i_df.if_u1.if_data != NULL);
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
|
||||
ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
|
||||
/*
|
||||
* Compute entry (and change in) size.
|
||||
*/
|
||||
add_entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
|
||||
add_entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
|
||||
incr_isize = add_entsize;
|
||||
objchange = 0;
|
||||
#if XFS_BIG_INUMS
|
||||
|
@ -392,7 +392,7 @@ xfs_dir2_sf_addname_easy(
|
|||
/*
|
||||
* Grow the in-inode space.
|
||||
*/
|
||||
xfs_idata_realloc(dp, XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen),
|
||||
xfs_idata_realloc(dp, xfs_dir2_sf_entsize_byname(sfp, args->namelen),
|
||||
XFS_DATA_FORK);
|
||||
/*
|
||||
* Need to set up again due to realloc of the inode data.
|
||||
|
@ -403,10 +403,10 @@ xfs_dir2_sf_addname_easy(
|
|||
* Fill in the new entry.
|
||||
*/
|
||||
sfep->namelen = args->namelen;
|
||||
XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
|
||||
xfs_dir2_sf_put_offset(sfep, offset);
|
||||
memcpy(sfep->name, args->name, sfep->namelen);
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
|
||||
XFS_DIR2_SF_INUMBERP(sfep));
|
||||
xfs_dir2_sf_put_inumber(sfp, &args->inumber,
|
||||
xfs_dir2_sf_inumberp(sfep));
|
||||
/*
|
||||
* Update the header and inode.
|
||||
*/
|
||||
|
@ -463,14 +463,14 @@ xfs_dir2_sf_addname_hard(
|
|||
* If it's going to end up at the end then oldsfep will point there.
|
||||
*/
|
||||
for (offset = XFS_DIR2_DATA_FIRST_OFFSET,
|
||||
oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp),
|
||||
add_datasize = XFS_DIR2_DATA_ENTSIZE(args->namelen),
|
||||
oldsfep = xfs_dir2_sf_firstentry(oldsfp),
|
||||
add_datasize = xfs_dir2_data_entsize(args->namelen),
|
||||
eof = (char *)oldsfep == &buf[old_isize];
|
||||
!eof;
|
||||
offset = new_offset + XFS_DIR2_DATA_ENTSIZE(oldsfep->namelen),
|
||||
oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep),
|
||||
offset = new_offset + xfs_dir2_data_entsize(oldsfep->namelen),
|
||||
oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep),
|
||||
eof = (char *)oldsfep == &buf[old_isize]) {
|
||||
new_offset = XFS_DIR2_SF_GET_OFFSET(oldsfep);
|
||||
new_offset = xfs_dir2_sf_get_offset(oldsfep);
|
||||
if (offset + add_datasize <= new_offset)
|
||||
break;
|
||||
}
|
||||
|
@ -495,10 +495,10 @@ xfs_dir2_sf_addname_hard(
|
|||
* Fill in the new entry, and update the header counts.
|
||||
*/
|
||||
sfep->namelen = args->namelen;
|
||||
XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
|
||||
xfs_dir2_sf_put_offset(sfep, offset);
|
||||
memcpy(sfep->name, args->name, sfep->namelen);
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
|
||||
XFS_DIR2_SF_INUMBERP(sfep));
|
||||
xfs_dir2_sf_put_inumber(sfp, &args->inumber,
|
||||
xfs_dir2_sf_inumberp(sfep));
|
||||
sfp->hdr.count++;
|
||||
#if XFS_BIG_INUMS
|
||||
if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
|
||||
|
@ -508,7 +508,7 @@ xfs_dir2_sf_addname_hard(
|
|||
* If there's more left to copy, do that.
|
||||
*/
|
||||
if (!eof) {
|
||||
sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
|
||||
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
|
||||
memcpy(sfep, oldsfep, old_isize - nbytes);
|
||||
}
|
||||
kmem_free(buf, old_isize);
|
||||
|
@ -544,9 +544,9 @@ xfs_dir2_sf_addname_pick(
|
|||
mp = dp->i_mount;
|
||||
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
size = XFS_DIR2_DATA_ENTSIZE(args->namelen);
|
||||
size = xfs_dir2_data_entsize(args->namelen);
|
||||
offset = XFS_DIR2_DATA_FIRST_OFFSET;
|
||||
sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
holefit = 0;
|
||||
/*
|
||||
* Loop over sf entries.
|
||||
|
@ -555,10 +555,10 @@ xfs_dir2_sf_addname_pick(
|
|||
*/
|
||||
for (i = 0; i < sfp->hdr.count; i++) {
|
||||
if (!holefit)
|
||||
holefit = offset + size <= XFS_DIR2_SF_GET_OFFSET(sfep);
|
||||
offset = XFS_DIR2_SF_GET_OFFSET(sfep) +
|
||||
XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
|
||||
sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
|
||||
holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
|
||||
offset = xfs_dir2_sf_get_offset(sfep) +
|
||||
xfs_dir2_data_entsize(sfep->namelen);
|
||||
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
|
||||
}
|
||||
/*
|
||||
* Calculate data bytes used excluding the new entry, if this
|
||||
|
@ -617,18 +617,18 @@ xfs_dir2_sf_check(
|
|||
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
offset = XFS_DIR2_DATA_FIRST_OFFSET;
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
|
||||
ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
|
||||
i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
|
||||
|
||||
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
i < sfp->hdr.count;
|
||||
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
|
||||
ASSERT(XFS_DIR2_SF_GET_OFFSET(sfep) >= offset);
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
|
||||
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
|
||||
ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
|
||||
ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
|
||||
i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
|
||||
offset =
|
||||
XFS_DIR2_SF_GET_OFFSET(sfep) +
|
||||
XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
|
||||
xfs_dir2_sf_get_offset(sfep) +
|
||||
xfs_dir2_data_entsize(sfep->namelen);
|
||||
}
|
||||
ASSERT(i8count == sfp->hdr.i8count);
|
||||
ASSERT(XFS_BIG_INUMS || i8count == 0);
|
||||
|
@ -671,7 +671,7 @@ xfs_dir2_sf_create(
|
|||
ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
|
||||
ASSERT(dp->i_df.if_bytes == 0);
|
||||
i8count = pino > XFS_DIR2_MAX_SHORT_INUM;
|
||||
size = XFS_DIR2_SF_HDR_SIZE(i8count);
|
||||
size = xfs_dir2_sf_hdr_size(i8count);
|
||||
/*
|
||||
* Make a buffer for the data.
|
||||
*/
|
||||
|
@ -684,7 +684,7 @@ xfs_dir2_sf_create(
|
|||
/*
|
||||
* Now can put in the inode number, since i8count is set.
|
||||
*/
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &pino, &sfp->hdr.parent);
|
||||
xfs_dir2_sf_put_inumber(sfp, &pino, &sfp->hdr.parent);
|
||||
sfp->hdr.count = 0;
|
||||
dp->i_d.di_size = size;
|
||||
xfs_dir2_sf_check(args);
|
||||
|
@ -727,12 +727,12 @@ xfs_dir2_sf_getdents(
|
|||
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
|
||||
ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
|
||||
ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
|
||||
|
||||
/*
|
||||
* If the block number in the offset is out of range, we're done.
|
||||
*/
|
||||
if (XFS_DIR2_DATAPTR_TO_DB(mp, dir_offset) > mp->m_dirdatablk) {
|
||||
if (xfs_dir2_dataptr_to_db(mp, dir_offset) > mp->m_dirdatablk) {
|
||||
*eofp = 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -747,9 +747,9 @@ xfs_dir2_sf_getdents(
|
|||
* Put . entry unless we're starting past it.
|
||||
*/
|
||||
if (dir_offset <=
|
||||
XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
XFS_DIR2_DATA_DOT_OFFSET)) {
|
||||
p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0,
|
||||
p.cook = xfs_dir2_db_off_to_dataptr(mp, 0,
|
||||
XFS_DIR2_DATA_DOTDOT_OFFSET);
|
||||
p.ino = dp->i_ino;
|
||||
#if XFS_BIG_INUMS
|
||||
|
@ -762,7 +762,7 @@ xfs_dir2_sf_getdents(
|
|||
|
||||
if (!p.done) {
|
||||
uio->uio_offset =
|
||||
XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
XFS_DIR2_DATA_DOT_OFFSET);
|
||||
return error;
|
||||
}
|
||||
|
@ -772,11 +772,11 @@ xfs_dir2_sf_getdents(
|
|||
* Put .. entry unless we're starting past it.
|
||||
*/
|
||||
if (dir_offset <=
|
||||
XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
XFS_DIR2_DATA_DOTDOT_OFFSET)) {
|
||||
p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
XFS_DIR2_DATA_FIRST_OFFSET);
|
||||
p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
|
||||
p.ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
|
||||
#if XFS_BIG_INUMS
|
||||
p.ino += mp->m_inoadd;
|
||||
#endif
|
||||
|
@ -787,7 +787,7 @@ xfs_dir2_sf_getdents(
|
|||
|
||||
if (!p.done) {
|
||||
uio->uio_offset =
|
||||
XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
XFS_DIR2_DATA_DOTDOT_OFFSET);
|
||||
return error;
|
||||
}
|
||||
|
@ -796,23 +796,23 @@ xfs_dir2_sf_getdents(
|
|||
/*
|
||||
* Loop while there are more entries and put'ing works.
|
||||
*/
|
||||
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
i < sfp->hdr.count;
|
||||
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
|
||||
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
|
||||
|
||||
off = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
XFS_DIR2_SF_GET_OFFSET(sfep));
|
||||
off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
xfs_dir2_sf_get_offset(sfep));
|
||||
|
||||
if (dir_offset > off)
|
||||
continue;
|
||||
|
||||
p.namelen = sfep->namelen;
|
||||
|
||||
p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
|
||||
XFS_DIR2_SF_GET_OFFSET(sfep) +
|
||||
XFS_DIR2_DATA_ENTSIZE(p.namelen));
|
||||
p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
|
||||
xfs_dir2_sf_get_offset(sfep) +
|
||||
xfs_dir2_data_entsize(p.namelen));
|
||||
|
||||
p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
|
||||
p.ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
|
||||
#if XFS_BIG_INUMS
|
||||
p.ino += mp->m_inoadd;
|
||||
#endif
|
||||
|
@ -832,7 +832,7 @@ xfs_dir2_sf_getdents(
|
|||
*eofp = 1;
|
||||
|
||||
uio->uio_offset =
|
||||
XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
|
||||
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -865,7 +865,7 @@ xfs_dir2_sf_lookup(
|
|||
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
|
||||
ASSERT(dp->i_df.if_u1.if_data != NULL);
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
|
||||
ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
|
||||
/*
|
||||
* Special case for .
|
||||
*/
|
||||
|
@ -878,21 +878,21 @@ xfs_dir2_sf_lookup(
|
|||
*/
|
||||
if (args->namelen == 2 &&
|
||||
args->name[0] == '.' && args->name[1] == '.') {
|
||||
args->inumber = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
|
||||
args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
|
||||
return XFS_ERROR(EEXIST);
|
||||
}
|
||||
/*
|
||||
* Loop over all the entries trying to match ours.
|
||||
*/
|
||||
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
i < sfp->hdr.count;
|
||||
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
|
||||
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
|
||||
if (sfep->namelen == args->namelen &&
|
||||
sfep->name[0] == args->name[0] &&
|
||||
memcmp(args->name, sfep->name, args->namelen) == 0) {
|
||||
args->inumber =
|
||||
XFS_DIR2_SF_GET_INUMBER(sfp,
|
||||
XFS_DIR2_SF_INUMBERP(sfep));
|
||||
xfs_dir2_sf_get_inumber(sfp,
|
||||
xfs_dir2_sf_inumberp(sfep));
|
||||
return XFS_ERROR(EEXIST);
|
||||
}
|
||||
}
|
||||
|
@ -934,19 +934,19 @@ xfs_dir2_sf_removename(
|
|||
ASSERT(dp->i_df.if_bytes == oldsize);
|
||||
ASSERT(dp->i_df.if_u1.if_data != NULL);
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
ASSERT(oldsize >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
|
||||
ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
|
||||
/*
|
||||
* Loop over the old directory entries.
|
||||
* Find the one we're deleting.
|
||||
*/
|
||||
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
i < sfp->hdr.count;
|
||||
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
|
||||
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
|
||||
if (sfep->namelen == args->namelen &&
|
||||
sfep->name[0] == args->name[0] &&
|
||||
memcmp(sfep->name, args->name, args->namelen) == 0) {
|
||||
ASSERT(XFS_DIR2_SF_GET_INUMBER(sfp,
|
||||
XFS_DIR2_SF_INUMBERP(sfep)) ==
|
||||
ASSERT(xfs_dir2_sf_get_inumber(sfp,
|
||||
xfs_dir2_sf_inumberp(sfep)) ==
|
||||
args->inumber);
|
||||
break;
|
||||
}
|
||||
|
@ -961,7 +961,7 @@ xfs_dir2_sf_removename(
|
|||
* Calculate sizes.
|
||||
*/
|
||||
byteoff = (int)((char *)sfep - (char *)sfp);
|
||||
entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
|
||||
entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
|
||||
newsize = oldsize - entsize;
|
||||
/*
|
||||
* Copy the part if any after the removed entry, sliding it down.
|
||||
|
@ -1027,7 +1027,7 @@ xfs_dir2_sf_replace(
|
|||
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
|
||||
ASSERT(dp->i_df.if_u1.if_data != NULL);
|
||||
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
|
||||
ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
|
||||
ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
|
||||
#if XFS_BIG_INUMS
|
||||
/*
|
||||
* New inode number is large, and need to convert to 8-byte inodes.
|
||||
|
@ -1067,28 +1067,28 @@ xfs_dir2_sf_replace(
|
|||
if (args->namelen == 2 &&
|
||||
args->name[0] == '.' && args->name[1] == '.') {
|
||||
#if XFS_BIG_INUMS || defined(DEBUG)
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
|
||||
ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
|
||||
ASSERT(args->inumber != ino);
|
||||
#endif
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber, &sfp->hdr.parent);
|
||||
xfs_dir2_sf_put_inumber(sfp, &args->inumber, &sfp->hdr.parent);
|
||||
}
|
||||
/*
|
||||
* Normal entry, look for the name.
|
||||
*/
|
||||
else {
|
||||
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
|
||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
|
||||
i < sfp->hdr.count;
|
||||
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
|
||||
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
|
||||
if (sfep->namelen == args->namelen &&
|
||||
sfep->name[0] == args->name[0] &&
|
||||
memcmp(args->name, sfep->name, args->namelen) == 0) {
|
||||
#if XFS_BIG_INUMS || defined(DEBUG)
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(sfp,
|
||||
XFS_DIR2_SF_INUMBERP(sfep));
|
||||
ino = xfs_dir2_sf_get_inumber(sfp,
|
||||
xfs_dir2_sf_inumberp(sfep));
|
||||
ASSERT(args->inumber != ino);
|
||||
#endif
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
|
||||
XFS_DIR2_SF_INUMBERP(sfep));
|
||||
xfs_dir2_sf_put_inumber(sfp, &args->inumber,
|
||||
xfs_dir2_sf_inumberp(sfep));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1189,22 +1189,22 @@ xfs_dir2_sf_toino4(
|
|||
*/
|
||||
sfp->hdr.count = oldsfp->hdr.count;
|
||||
sfp->hdr.i8count = 0;
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
|
||||
ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
|
||||
xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
|
||||
/*
|
||||
* Copy the entries field by field.
|
||||
*/
|
||||
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
|
||||
oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
|
||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
|
||||
oldsfep = xfs_dir2_sf_firstentry(oldsfp);
|
||||
i < sfp->hdr.count;
|
||||
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
|
||||
oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
|
||||
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
|
||||
oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
|
||||
sfep->namelen = oldsfep->namelen;
|
||||
sfep->offset = oldsfep->offset;
|
||||
memcpy(sfep->name, oldsfep->name, sfep->namelen);
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
|
||||
XFS_DIR2_SF_INUMBERP(oldsfep));
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
|
||||
ino = xfs_dir2_sf_get_inumber(oldsfp,
|
||||
xfs_dir2_sf_inumberp(oldsfep));
|
||||
xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
|
||||
}
|
||||
/*
|
||||
* Clean up the inode.
|
||||
|
@ -1266,22 +1266,22 @@ xfs_dir2_sf_toino8(
|
|||
*/
|
||||
sfp->hdr.count = oldsfp->hdr.count;
|
||||
sfp->hdr.i8count = 1;
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
|
||||
ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
|
||||
xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
|
||||
/*
|
||||
* Copy the entries field by field.
|
||||
*/
|
||||
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
|
||||
oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
|
||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
|
||||
oldsfep = xfs_dir2_sf_firstentry(oldsfp);
|
||||
i < sfp->hdr.count;
|
||||
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
|
||||
oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
|
||||
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
|
||||
oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
|
||||
sfep->namelen = oldsfep->namelen;
|
||||
sfep->offset = oldsfep->offset;
|
||||
memcpy(sfep->name, oldsfep->name, sfep->namelen);
|
||||
ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
|
||||
XFS_DIR2_SF_INUMBERP(oldsfep));
|
||||
XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
|
||||
ino = xfs_dir2_sf_get_inumber(oldsfp,
|
||||
xfs_dir2_sf_inumberp(oldsfep));
|
||||
xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
|
||||
}
|
||||
/*
|
||||
* Clean up the inode.
|
||||
|
|
|
@ -90,7 +90,6 @@ typedef struct xfs_dir2_sf {
|
|||
xfs_dir2_sf_entry_t list[1]; /* shortform entries */
|
||||
} xfs_dir2_sf_t;
|
||||
|
||||
#define XFS_DIR2_SF_HDR_SIZE(i8count) xfs_dir2_sf_hdr_size(i8count)
|
||||
static inline int xfs_dir2_sf_hdr_size(int i8count)
|
||||
{
|
||||
return ((uint)sizeof(xfs_dir2_sf_hdr_t) - \
|
||||
|
@ -98,14 +97,11 @@ static inline int xfs_dir2_sf_hdr_size(int i8count)
|
|||
((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_INUMBERP(sfep) xfs_dir2_sf_inumberp(sfep)
|
||||
static inline xfs_dir2_inou_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep)
|
||||
{
|
||||
return (xfs_dir2_inou_t *)&(sfep)->name[(sfep)->namelen];
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_GET_INUMBER(sfp, from) \
|
||||
xfs_dir2_sf_get_inumber(sfp, from)
|
||||
static inline xfs_intino_t
|
||||
xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
|
||||
{
|
||||
|
@ -114,8 +110,6 @@ xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
|
|||
(xfs_intino_t)XFS_GET_DIR_INO8((from)->i8));
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_PUT_INUMBER(sfp,from,to) \
|
||||
xfs_dir2_sf_put_inumber(sfp,from,to)
|
||||
static inline void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
|
||||
xfs_dir2_inou_t *to)
|
||||
{
|
||||
|
@ -125,24 +119,18 @@ static inline void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
|
|||
XFS_PUT_DIR_INO8(*(from), (to)->i8);
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_GET_OFFSET(sfep) \
|
||||
xfs_dir2_sf_get_offset(sfep)
|
||||
static inline xfs_dir2_data_aoff_t
|
||||
xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
|
||||
{
|
||||
return INT_GET_UNALIGNED_16_BE(&(sfep)->offset.i);
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_PUT_OFFSET(sfep,off) \
|
||||
xfs_dir2_sf_put_offset(sfep,off)
|
||||
static inline void
|
||||
xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
|
||||
{
|
||||
INT_SET_UNALIGNED_16_BE(&(sfep)->offset.i, off);
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_ENTSIZE_BYNAME(sfp,len) \
|
||||
xfs_dir2_sf_entsize_byname(sfp,len)
|
||||
static inline int xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
|
||||
{
|
||||
return ((uint)sizeof(xfs_dir2_sf_entry_t) - 1 + (len) - \
|
||||
|
@ -150,8 +138,6 @@ static inline int xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
|
|||
((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep) \
|
||||
xfs_dir2_sf_entsize_byentry(sfp,sfep)
|
||||
static inline int
|
||||
xfs_dir2_sf_entsize_byentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
|
||||
{
|
||||
|
@ -160,19 +146,17 @@ xfs_dir2_sf_entsize_byentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
|
|||
((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_FIRSTENTRY(sfp) xfs_dir2_sf_firstentry(sfp)
|
||||
static inline xfs_dir2_sf_entry_t *xfs_dir2_sf_firstentry(xfs_dir2_sf_t *sfp)
|
||||
{
|
||||
return ((xfs_dir2_sf_entry_t *) \
|
||||
((char *)(sfp) + XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count)));
|
||||
((char *)(sfp) + xfs_dir2_sf_hdr_size(sfp->hdr.i8count)));
|
||||
}
|
||||
|
||||
#define XFS_DIR2_SF_NEXTENTRY(sfp,sfep) xfs_dir2_sf_nextentry(sfp,sfep)
|
||||
static inline xfs_dir2_sf_entry_t *
|
||||
xfs_dir2_sf_nextentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
|
||||
{
|
||||
return ((xfs_dir2_sf_entry_t *) \
|
||||
((char *)(sfep) + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep)));
|
||||
((char *)(sfep) + xfs_dir2_sf_entsize_byentry(sfp,sfep)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,771 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "xfs.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_inum.h"
|
||||
#include "xfs_dir2.h"
|
||||
#include "xfs_dir2_sf.h"
|
||||
#include "xfs_attr_sf.h"
|
||||
#include "xfs_dinode.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "xfs_dmapi.h"
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_sb.h"
|
||||
#include "xfs_mount.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_utils.h"
|
||||
#include "xfs_mru_cache.h"
|
||||
#include "xfs_filestream.h"
|
||||
|
||||
#ifdef XFS_FILESTREAMS_TRACE
|
||||
|
||||
ktrace_t *xfs_filestreams_trace_buf;
|
||||
|
||||
STATIC void
|
||||
xfs_filestreams_trace(
|
||||
xfs_mount_t *mp, /* mount point */
|
||||
int type, /* type of trace */
|
||||
const char *func, /* source function */
|
||||
int line, /* source line number */
|
||||
__psunsigned_t arg0,
|
||||
__psunsigned_t arg1,
|
||||
__psunsigned_t arg2,
|
||||
__psunsigned_t arg3,
|
||||
__psunsigned_t arg4,
|
||||
__psunsigned_t arg5)
|
||||
{
|
||||
ktrace_enter(xfs_filestreams_trace_buf,
|
||||
(void *)(__psint_t)(type | (line << 16)),
|
||||
(void *)func,
|
||||
(void *)(__psunsigned_t)current_pid(),
|
||||
(void *)mp,
|
||||
(void *)(__psunsigned_t)arg0,
|
||||
(void *)(__psunsigned_t)arg1,
|
||||
(void *)(__psunsigned_t)arg2,
|
||||
(void *)(__psunsigned_t)arg3,
|
||||
(void *)(__psunsigned_t)arg4,
|
||||
(void *)(__psunsigned_t)arg5,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
#define TRACE0(mp,t) TRACE6(mp,t,0,0,0,0,0,0)
|
||||
#define TRACE1(mp,t,a0) TRACE6(mp,t,a0,0,0,0,0,0)
|
||||
#define TRACE2(mp,t,a0,a1) TRACE6(mp,t,a0,a1,0,0,0,0)
|
||||
#define TRACE3(mp,t,a0,a1,a2) TRACE6(mp,t,a0,a1,a2,0,0,0)
|
||||
#define TRACE4(mp,t,a0,a1,a2,a3) TRACE6(mp,t,a0,a1,a2,a3,0,0)
|
||||
#define TRACE5(mp,t,a0,a1,a2,a3,a4) TRACE6(mp,t,a0,a1,a2,a3,a4,0)
|
||||
#define TRACE6(mp,t,a0,a1,a2,a3,a4,a5) \
|
||||
xfs_filestreams_trace(mp, t, __FUNCTION__, __LINE__, \
|
||||
(__psunsigned_t)a0, (__psunsigned_t)a1, \
|
||||
(__psunsigned_t)a2, (__psunsigned_t)a3, \
|
||||
(__psunsigned_t)a4, (__psunsigned_t)a5)
|
||||
|
||||
#define TRACE_AG_SCAN(mp, ag, ag2) \
|
||||
TRACE2(mp, XFS_FSTRM_KTRACE_AGSCAN, ag, ag2);
|
||||
#define TRACE_AG_PICK1(mp, max_ag, maxfree) \
|
||||
TRACE2(mp, XFS_FSTRM_KTRACE_AGPICK1, max_ag, maxfree);
|
||||
#define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag) \
|
||||
TRACE6(mp, XFS_FSTRM_KTRACE_AGPICK2, ag, ag2, \
|
||||
cnt, free, scan, flag)
|
||||
#define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2) \
|
||||
TRACE5(mp, XFS_FSTRM_KTRACE_UPDATE, ip, ag, cnt, ag2, cnt2)
|
||||
#define TRACE_FREE(mp, ip, pip, ag, cnt) \
|
||||
TRACE4(mp, XFS_FSTRM_KTRACE_FREE, ip, pip, ag, cnt)
|
||||
#define TRACE_LOOKUP(mp, ip, pip, ag, cnt) \
|
||||
TRACE4(mp, XFS_FSTRM_KTRACE_ITEM_LOOKUP, ip, pip, ag, cnt)
|
||||
#define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt) \
|
||||
TRACE4(mp, XFS_FSTRM_KTRACE_ASSOCIATE, ip, pip, ag, cnt)
|
||||
#define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt) \
|
||||
TRACE6(mp, XFS_FSTRM_KTRACE_MOVEAG, ip, pip, oag, ocnt, nag, ncnt)
|
||||
#define TRACE_ORPHAN(mp, ip, ag) \
|
||||
TRACE2(mp, XFS_FSTRM_KTRACE_ORPHAN, ip, ag);
|
||||
|
||||
|
||||
#else
|
||||
#define TRACE_AG_SCAN(mp, ag, ag2)
|
||||
#define TRACE_AG_PICK1(mp, max_ag, maxfree)
|
||||
#define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag)
|
||||
#define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2)
|
||||
#define TRACE_FREE(mp, ip, pip, ag, cnt)
|
||||
#define TRACE_LOOKUP(mp, ip, pip, ag, cnt)
|
||||
#define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt)
|
||||
#define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt)
|
||||
#define TRACE_ORPHAN(mp, ip, ag)
|
||||
#endif
|
||||
|
||||
static kmem_zone_t *item_zone;
|
||||
|
||||
/*
|
||||
* Structure for associating a file or a directory with an allocation group.
|
||||
* The parent directory pointer is only needed for files, but since there will
|
||||
* generally be vastly more files than directories in the cache, using the same
|
||||
* data structure simplifies the code with very little memory overhead.
|
||||
*/
|
||||
typedef struct fstrm_item
|
||||
{
|
||||
xfs_agnumber_t ag; /* AG currently in use for the file/directory. */
|
||||
xfs_inode_t *ip; /* inode self-pointer. */
|
||||
xfs_inode_t *pip; /* Parent directory inode pointer. */
|
||||
} fstrm_item_t;
|
||||
|
||||
|
||||
/*
|
||||
* Scan the AGs starting at startag looking for an AG that isn't in use and has
|
||||
* at least minlen blocks free.
|
||||
*/
|
||||
static int
|
||||
_xfs_filestream_pick_ag(
|
||||
xfs_mount_t *mp,
|
||||
xfs_agnumber_t startag,
|
||||
xfs_agnumber_t *agp,
|
||||
int flags,
|
||||
xfs_extlen_t minlen)
|
||||
{
|
||||
int err, trylock, nscan;
|
||||
xfs_extlen_t delta, longest, need, free, minfree, maxfree = 0;
|
||||
xfs_agnumber_t ag, max_ag = NULLAGNUMBER;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
/* 2% of an AG's blocks must be free for it to be chosen. */
|
||||
minfree = mp->m_sb.sb_agblocks / 50;
|
||||
|
||||
ag = startag;
|
||||
*agp = NULLAGNUMBER;
|
||||
|
||||
/* For the first pass, don't sleep trying to init the per-AG. */
|
||||
trylock = XFS_ALLOC_FLAG_TRYLOCK;
|
||||
|
||||
for (nscan = 0; 1; nscan++) {
|
||||
|
||||
TRACE_AG_SCAN(mp, ag, xfs_filestream_peek_ag(mp, ag));
|
||||
|
||||
pag = mp->m_perag + ag;
|
||||
|
||||
if (!pag->pagf_init) {
|
||||
err = xfs_alloc_pagf_init(mp, NULL, ag, trylock);
|
||||
if (err && !trylock)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Might fail sometimes during the 1st pass with trylock set. */
|
||||
if (!pag->pagf_init)
|
||||
goto next_ag;
|
||||
|
||||
/* Keep track of the AG with the most free blocks. */
|
||||
if (pag->pagf_freeblks > maxfree) {
|
||||
maxfree = pag->pagf_freeblks;
|
||||
max_ag = ag;
|
||||
}
|
||||
|
||||
/*
|
||||
* The AG reference count does two things: it enforces mutual
|
||||
* exclusion when examining the suitability of an AG in this
|
||||
* loop, and it guards against two filestreams being established
|
||||
* in the same AG as each other.
|
||||
*/
|
||||
if (xfs_filestream_get_ag(mp, ag) > 1) {
|
||||
xfs_filestream_put_ag(mp, ag);
|
||||
goto next_ag;
|
||||
}
|
||||
|
||||
need = XFS_MIN_FREELIST_PAG(pag, mp);
|
||||
delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
|
||||
longest = (pag->pagf_longest > delta) ?
|
||||
(pag->pagf_longest - delta) :
|
||||
(pag->pagf_flcount > 0 || pag->pagf_longest > 0);
|
||||
|
||||
if (((minlen && longest >= minlen) ||
|
||||
(!minlen && pag->pagf_freeblks >= minfree)) &&
|
||||
(!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) ||
|
||||
(flags & XFS_PICK_LOWSPACE))) {
|
||||
|
||||
/* Break out, retaining the reference on the AG. */
|
||||
free = pag->pagf_freeblks;
|
||||
*agp = ag;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Drop the reference on this AG, it's not usable. */
|
||||
xfs_filestream_put_ag(mp, ag);
|
||||
next_ag:
|
||||
/* Move to the next AG, wrapping to AG 0 if necessary. */
|
||||
if (++ag >= mp->m_sb.sb_agcount)
|
||||
ag = 0;
|
||||
|
||||
/* If a full pass of the AGs hasn't been done yet, continue. */
|
||||
if (ag != startag)
|
||||
continue;
|
||||
|
||||
/* Allow sleeping in xfs_alloc_pagf_init() on the 2nd pass. */
|
||||
if (trylock != 0) {
|
||||
trylock = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Finally, if lowspace wasn't set, set it for the 3rd pass. */
|
||||
if (!(flags & XFS_PICK_LOWSPACE)) {
|
||||
flags |= XFS_PICK_LOWSPACE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the AG with the most free space, regardless of whether
|
||||
* it's already in use by another filestream.
|
||||
*/
|
||||
if (max_ag != NULLAGNUMBER) {
|
||||
xfs_filestream_get_ag(mp, max_ag);
|
||||
TRACE_AG_PICK1(mp, max_ag, maxfree);
|
||||
free = maxfree;
|
||||
*agp = max_ag;
|
||||
break;
|
||||
}
|
||||
|
||||
/* take AG 0 if none matched */
|
||||
TRACE_AG_PICK1(mp, max_ag, maxfree);
|
||||
*agp = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE_AG_PICK2(mp, startag, *agp, xfs_filestream_peek_ag(mp, *agp),
|
||||
free, nscan, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the allocation group number for a file or a directory, updating inode
|
||||
* references and per-AG references as appropriate. Must be called with the
|
||||
* m_peraglock held in read mode.
|
||||
*/
|
||||
static int
|
||||
_xfs_filestream_update_ag(
|
||||
xfs_inode_t *ip,
|
||||
xfs_inode_t *pip,
|
||||
xfs_agnumber_t ag)
|
||||
{
|
||||
int err = 0;
|
||||
xfs_mount_t *mp;
|
||||
xfs_mru_cache_t *cache;
|
||||
fstrm_item_t *item;
|
||||
xfs_agnumber_t old_ag;
|
||||
xfs_inode_t *old_pip;
|
||||
|
||||
/*
|
||||
* Either ip is a regular file and pip is a directory, or ip is a
|
||||
* directory and pip is NULL.
|
||||
*/
|
||||
ASSERT(ip && (((ip->i_d.di_mode & S_IFREG) && pip &&
|
||||
(pip->i_d.di_mode & S_IFDIR)) ||
|
||||
((ip->i_d.di_mode & S_IFDIR) && !pip)));
|
||||
|
||||
mp = ip->i_mount;
|
||||
cache = mp->m_filestream;
|
||||
|
||||
item = xfs_mru_cache_lookup(cache, ip->i_ino);
|
||||
if (item) {
|
||||
ASSERT(item->ip == ip);
|
||||
old_ag = item->ag;
|
||||
item->ag = ag;
|
||||
old_pip = item->pip;
|
||||
item->pip = pip;
|
||||
xfs_mru_cache_done(cache);
|
||||
|
||||
/*
|
||||
* If the AG has changed, drop the old ref and take a new one,
|
||||
* effectively transferring the reference from old to new AG.
|
||||
*/
|
||||
if (ag != old_ag) {
|
||||
xfs_filestream_put_ag(mp, old_ag);
|
||||
xfs_filestream_get_ag(mp, ag);
|
||||
}
|
||||
|
||||
/*
|
||||
* If ip is a file and its pip has changed, drop the old ref and
|
||||
* take a new one.
|
||||
*/
|
||||
if (pip && pip != old_pip) {
|
||||
IRELE(old_pip);
|
||||
IHOLD(pip);
|
||||
}
|
||||
|
||||
TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag),
|
||||
ag, xfs_filestream_peek_ag(mp, ag));
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = kmem_zone_zalloc(item_zone, KM_MAYFAIL);
|
||||
if (!item)
|
||||
return ENOMEM;
|
||||
|
||||
item->ag = ag;
|
||||
item->ip = ip;
|
||||
item->pip = pip;
|
||||
|
||||
err = xfs_mru_cache_insert(cache, ip->i_ino, item);
|
||||
if (err) {
|
||||
kmem_zone_free(item_zone, item);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Take a reference on the AG. */
|
||||
xfs_filestream_get_ag(mp, ag);
|
||||
|
||||
/*
|
||||
* Take a reference on the inode itself regardless of whether it's a
|
||||
* regular file or a directory.
|
||||
*/
|
||||
IHOLD(ip);
|
||||
|
||||
/*
|
||||
* In the case of a regular file, take a reference on the parent inode
|
||||
* as well to ensure it remains in-core.
|
||||
*/
|
||||
if (pip)
|
||||
IHOLD(pip);
|
||||
|
||||
TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag),
|
||||
ag, xfs_filestream_peek_ag(mp, ag));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* xfs_fstrm_free_func(): callback for freeing cached stream items. */
|
||||
void
|
||||
xfs_fstrm_free_func(
|
||||
xfs_ino_t ino,
|
||||
fstrm_item_t *item)
|
||||
{
|
||||
xfs_inode_t *ip = item->ip;
|
||||
int ref;
|
||||
|
||||
ASSERT(ip->i_ino == ino);
|
||||
|
||||
xfs_iflags_clear(ip, XFS_IFILESTREAM);
|
||||
|
||||
/* Drop the reference taken on the AG when the item was added. */
|
||||
ref = xfs_filestream_put_ag(ip->i_mount, item->ag);
|
||||
|
||||
ASSERT(ref >= 0);
|
||||
TRACE_FREE(ip->i_mount, ip, item->pip, item->ag,
|
||||
xfs_filestream_peek_ag(ip->i_mount, item->ag));
|
||||
|
||||
/*
|
||||
* _xfs_filestream_update_ag() always takes a reference on the inode
|
||||
* itself, whether it's a file or a directory. Release it here.
|
||||
* This can result in the inode being freed and so we must
|
||||
* not hold any inode locks when freeing filesstreams objects
|
||||
* otherwise we can deadlock here.
|
||||
*/
|
||||
IRELE(ip);
|
||||
|
||||
/*
|
||||
* In the case of a regular file, _xfs_filestream_update_ag() also
|
||||
* takes a ref on the parent inode to keep it in-core. Release that
|
||||
* too.
|
||||
*/
|
||||
if (item->pip)
|
||||
IRELE(item->pip);
|
||||
|
||||
/* Finally, free the memory allocated for the item. */
|
||||
kmem_zone_free(item_zone, item);
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_filestream_init() is called at xfs initialisation time to set up the
|
||||
* memory zone that will be used for filestream data structure allocation.
|
||||
*/
|
||||
int
|
||||
xfs_filestream_init(void)
|
||||
{
|
||||
item_zone = kmem_zone_init(sizeof(fstrm_item_t), "fstrm_item");
|
||||
#ifdef XFS_FILESTREAMS_TRACE
|
||||
xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP);
|
||||
#endif
|
||||
return item_zone ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_filestream_uninit() is called at xfs termination time to destroy the
|
||||
* memory zone that was used for filestream data structure allocation.
|
||||
*/
|
||||
void
|
||||
xfs_filestream_uninit(void)
|
||||
{
|
||||
#ifdef XFS_FILESTREAMS_TRACE
|
||||
ktrace_free(xfs_filestreams_trace_buf);
|
||||
#endif
|
||||
kmem_zone_destroy(item_zone);
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_filestream_mount() is called when a file system is mounted with the
|
||||
* filestream option. It is responsible for allocating the data structures
|
||||
* needed to track the new file system's file streams.
|
||||
*/
|
||||
int
|
||||
xfs_filestream_mount(
|
||||
xfs_mount_t *mp)
|
||||
{
|
||||
int err;
|
||||
unsigned int lifetime, grp_count;
|
||||
|
||||
/*
|
||||
* The filestream timer tunable is currently fixed within the range of
|
||||
* one second to four minutes, with five seconds being the default. The
|
||||
* group count is somewhat arbitrary, but it'd be nice to adhere to the
|
||||
* timer tunable to within about 10 percent. This requires at least 10
|
||||
* groups.
|
||||
*/
|
||||
lifetime = xfs_fstrm_centisecs * 10;
|
||||
grp_count = 10;
|
||||
|
||||
err = xfs_mru_cache_create(&mp->m_filestream, lifetime, grp_count,
|
||||
(xfs_mru_cache_free_func_t)xfs_fstrm_free_func);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_filestream_unmount() is called when a file system that was mounted with
|
||||
* the filestream option is unmounted. It drains the data structures created
|
||||
* to track the file system's file streams and frees all the memory that was
|
||||
* allocated.
|
||||
*/
|
||||
void
|
||||
xfs_filestream_unmount(
|
||||
xfs_mount_t *mp)
|
||||
{
|
||||
xfs_mru_cache_destroy(mp->m_filestream);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the mount point's m_perag array is going to be reallocated, all
|
||||
* outstanding cache entries must be flushed to avoid accessing reference count
|
||||
* addresses that have been freed. The call to xfs_filestream_flush() must be
|
||||
* made inside the block that holds the m_peraglock in write mode to do the
|
||||
* reallocation.
|
||||
*/
|
||||
void
|
||||
xfs_filestream_flush(
|
||||
xfs_mount_t *mp)
|
||||
{
|
||||
/* point in time flush, so keep the reaper running */
|
||||
xfs_mru_cache_flush(mp->m_filestream, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the AG of the filestream the file or directory belongs to, or
|
||||
* NULLAGNUMBER otherwise.
|
||||
*/
|
||||
xfs_agnumber_t
|
||||
xfs_filestream_lookup_ag(
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
xfs_mru_cache_t *cache;
|
||||
fstrm_item_t *item;
|
||||
xfs_agnumber_t ag;
|
||||
int ref;
|
||||
|
||||
if (!(ip->i_d.di_mode & (S_IFREG | S_IFDIR))) {
|
||||
ASSERT(0);
|
||||
return NULLAGNUMBER;
|
||||
}
|
||||
|
||||
cache = ip->i_mount->m_filestream;
|
||||
item = xfs_mru_cache_lookup(cache, ip->i_ino);
|
||||
if (!item) {
|
||||
TRACE_LOOKUP(ip->i_mount, ip, NULL, NULLAGNUMBER, 0);
|
||||
return NULLAGNUMBER;
|
||||
}
|
||||
|
||||
ASSERT(ip == item->ip);
|
||||
ag = item->ag;
|
||||
ref = xfs_filestream_peek_ag(ip->i_mount, ag);
|
||||
xfs_mru_cache_done(cache);
|
||||
|
||||
TRACE_LOOKUP(ip->i_mount, ip, item->pip, ag, ref);
|
||||
return ag;
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_filestream_associate() should only be called to associate a regular file
|
||||
* with its parent directory. Calling it with a child directory isn't
|
||||
* appropriate because filestreams don't apply to entire directory hierarchies.
|
||||
* Creating a file in a child directory of an existing filestream directory
|
||||
* starts a new filestream with its own allocation group association.
|
||||
*
|
||||
* Returns < 0 on error, 0 if successful association occurred, > 0 if
|
||||
* we failed to get an association because of locking issues.
|
||||
*/
|
||||
int
|
||||
xfs_filestream_associate(
|
||||
xfs_inode_t *pip,
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
xfs_mount_t *mp;
|
||||
xfs_mru_cache_t *cache;
|
||||
fstrm_item_t *item;
|
||||
xfs_agnumber_t ag, rotorstep, startag;
|
||||
int err = 0;
|
||||
|
||||
ASSERT(pip->i_d.di_mode & S_IFDIR);
|
||||
ASSERT(ip->i_d.di_mode & S_IFREG);
|
||||
if (!(pip->i_d.di_mode & S_IFDIR) || !(ip->i_d.di_mode & S_IFREG))
|
||||
return -EINVAL;
|
||||
|
||||
mp = pip->i_mount;
|
||||
cache = mp->m_filestream;
|
||||
down_read(&mp->m_peraglock);
|
||||
|
||||
/*
|
||||
* We have a problem, Houston.
|
||||
*
|
||||
* Taking the iolock here violates inode locking order - we already
|
||||
* hold the ilock. Hence if we block getting this lock we may never
|
||||
* wake. Unfortunately, that means if we can't get the lock, we're
|
||||
* screwed in terms of getting a stream association - we can't spin
|
||||
* waiting for the lock because someone else is waiting on the lock we
|
||||
* hold and we cannot drop that as we are in a transaction here.
|
||||
*
|
||||
* Lucky for us, this inversion is rarely a problem because it's a
|
||||
* directory inode that we are trying to lock here and that means the
|
||||
* only place that matters is xfs_sync_inodes() and SYNC_DELWRI is
|
||||
* used. i.e. freeze, remount-ro, quotasync or unmount.
|
||||
*
|
||||
* So, if we can't get the iolock without sleeping then just give up
|
||||
*/
|
||||
if (!xfs_ilock_nowait(pip, XFS_IOLOCK_EXCL)) {
|
||||
up_read(&mp->m_peraglock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If the parent directory is already in the cache, use its AG. */
|
||||
item = xfs_mru_cache_lookup(cache, pip->i_ino);
|
||||
if (item) {
|
||||
ASSERT(item->ip == pip);
|
||||
ag = item->ag;
|
||||
xfs_mru_cache_done(cache);
|
||||
|
||||
TRACE_LOOKUP(mp, pip, pip, ag, xfs_filestream_peek_ag(mp, ag));
|
||||
err = _xfs_filestream_update_ag(ip, pip, ag);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the starting AG using the rotor for inode32, otherwise
|
||||
* use the directory inode's AG.
|
||||
*/
|
||||
if (mp->m_flags & XFS_MOUNT_32BITINODES) {
|
||||
rotorstep = xfs_rotorstep;
|
||||
startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount;
|
||||
mp->m_agfrotor = (mp->m_agfrotor + 1) %
|
||||
(mp->m_sb.sb_agcount * rotorstep);
|
||||
} else
|
||||
startag = XFS_INO_TO_AGNO(mp, pip->i_ino);
|
||||
|
||||
/* Pick a new AG for the parent inode starting at startag. */
|
||||
err = _xfs_filestream_pick_ag(mp, startag, &ag, 0, 0);
|
||||
if (err || ag == NULLAGNUMBER)
|
||||
goto exit_did_pick;
|
||||
|
||||
/* Associate the parent inode with the AG. */
|
||||
err = _xfs_filestream_update_ag(pip, NULL, ag);
|
||||
if (err)
|
||||
goto exit_did_pick;
|
||||
|
||||
/* Associate the file inode with the AG. */
|
||||
err = _xfs_filestream_update_ag(ip, pip, ag);
|
||||
if (err)
|
||||
goto exit_did_pick;
|
||||
|
||||
TRACE_ASSOCIATE(mp, ip, pip, ag, xfs_filestream_peek_ag(mp, ag));
|
||||
|
||||
exit_did_pick:
|
||||
/*
|
||||
* If _xfs_filestream_pick_ag() returned a valid AG, remove the
|
||||
* reference it took on it, since the file and directory will have taken
|
||||
* their own now if they were successfully cached.
|
||||
*/
|
||||
if (ag != NULLAGNUMBER)
|
||||
xfs_filestream_put_ag(mp, ag);
|
||||
|
||||
exit:
|
||||
xfs_iunlock(pip, XFS_IOLOCK_EXCL);
|
||||
up_read(&mp->m_peraglock);
|
||||
return -err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a new allocation group for the current file and its file stream. This
|
||||
* function is called by xfs_bmap_filestreams() with the mount point's per-ag
|
||||
* lock held.
|
||||
*/
|
||||
int
|
||||
xfs_filestream_new_ag(
|
||||
xfs_bmalloca_t *ap,
|
||||
xfs_agnumber_t *agp)
|
||||
{
|
||||
int flags, err;
|
||||
xfs_inode_t *ip, *pip = NULL;
|
||||
xfs_mount_t *mp;
|
||||
xfs_mru_cache_t *cache;
|
||||
xfs_extlen_t minlen;
|
||||
fstrm_item_t *dir, *file;
|
||||
xfs_agnumber_t ag = NULLAGNUMBER;
|
||||
|
||||
ip = ap->ip;
|
||||
mp = ip->i_mount;
|
||||
cache = mp->m_filestream;
|
||||
minlen = ap->alen;
|
||||
*agp = NULLAGNUMBER;
|
||||
|
||||
/*
|
||||
* Look for the file in the cache, removing it if it's found. Doing
|
||||
* this allows it to be held across the dir lookup that follows.
|
||||
*/
|
||||
file = xfs_mru_cache_remove(cache, ip->i_ino);
|
||||
if (file) {
|
||||
ASSERT(ip == file->ip);
|
||||
|
||||
/* Save the file's parent inode and old AG number for later. */
|
||||
pip = file->pip;
|
||||
ag = file->ag;
|
||||
|
||||
/* Look for the file's directory in the cache. */
|
||||
dir = xfs_mru_cache_lookup(cache, pip->i_ino);
|
||||
if (dir) {
|
||||
ASSERT(pip == dir->ip);
|
||||
|
||||
/*
|
||||
* If the directory has already moved on to a new AG,
|
||||
* use that AG as the new AG for the file. Don't
|
||||
* forget to twiddle the AG refcounts to match the
|
||||
* movement.
|
||||
*/
|
||||
if (dir->ag != file->ag) {
|
||||
xfs_filestream_put_ag(mp, file->ag);
|
||||
xfs_filestream_get_ag(mp, dir->ag);
|
||||
*agp = file->ag = dir->ag;
|
||||
}
|
||||
|
||||
xfs_mru_cache_done(cache);
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the file back in the cache. If this fails, the free
|
||||
* function needs to be called to tidy up in the same way as if
|
||||
* the item had simply expired from the cache.
|
||||
*/
|
||||
err = xfs_mru_cache_insert(cache, ip->i_ino, file);
|
||||
if (err) {
|
||||
xfs_fstrm_free_func(ip->i_ino, file);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the file's AG was moved to the directory's new AG, there's
|
||||
* nothing more to be done.
|
||||
*/
|
||||
if (*agp != NULLAGNUMBER) {
|
||||
TRACE_MOVEAG(mp, ip, pip,
|
||||
ag, xfs_filestream_peek_ag(mp, ag),
|
||||
*agp, xfs_filestream_peek_ag(mp, *agp));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the file's parent directory is known, take its iolock in exclusive
|
||||
* mode to prevent two sibling files from racing each other to migrate
|
||||
* themselves and their parent to different AGs.
|
||||
*/
|
||||
if (pip)
|
||||
xfs_ilock(pip, XFS_IOLOCK_EXCL);
|
||||
|
||||
/*
|
||||
* A new AG needs to be found for the file. If the file's parent
|
||||
* directory is also known, it will be moved to the new AG as well to
|
||||
* ensure that files created inside it in future use the new AG.
|
||||
*/
|
||||
ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount;
|
||||
flags = (ap->userdata ? XFS_PICK_USERDATA : 0) |
|
||||
(ap->low ? XFS_PICK_LOWSPACE : 0);
|
||||
|
||||
err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen);
|
||||
if (err || *agp == NULLAGNUMBER)
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* If the file wasn't found in the file cache, then its parent directory
|
||||
* inode isn't known. For this to have happened, the file must either
|
||||
* be pre-existing, or it was created long enough ago that its cache
|
||||
* entry has expired. This isn't the sort of usage that the filestreams
|
||||
* allocator is trying to optimise, so there's no point trying to track
|
||||
* its new AG somehow in the filestream data structures.
|
||||
*/
|
||||
if (!pip) {
|
||||
TRACE_ORPHAN(mp, ip, *agp);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Associate the parent inode with the AG. */
|
||||
err = _xfs_filestream_update_ag(pip, NULL, *agp);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
/* Associate the file inode with the AG. */
|
||||
err = _xfs_filestream_update_ag(ip, pip, *agp);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
TRACE_MOVEAG(mp, ip, pip, NULLAGNUMBER, 0,
|
||||
*agp, xfs_filestream_peek_ag(mp, *agp));
|
||||
|
||||
exit:
|
||||
/*
|
||||
* If _xfs_filestream_pick_ag() returned a valid AG, remove the
|
||||
* reference it took on it, since the file and directory will have taken
|
||||
* their own now if they were successfully cached.
|
||||
*/
|
||||
if (*agp != NULLAGNUMBER)
|
||||
xfs_filestream_put_ag(mp, *agp);
|
||||
else
|
||||
*agp = 0;
|
||||
|
||||
if (pip)
|
||||
xfs_iunlock(pip, XFS_IOLOCK_EXCL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an association between an inode and a filestream object.
|
||||
* Typically this is done on last close of an unlinked file.
|
||||
*/
|
||||
void
|
||||
xfs_filestream_deassociate(
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
xfs_mru_cache_t *cache = ip->i_mount->m_filestream;
|
||||
|
||||
xfs_mru_cache_delete(cache, ip->i_ino);
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __XFS_FILESTREAM_H__
|
||||
#define __XFS_FILESTREAM_H__
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct xfs_mount;
|
||||
struct xfs_inode;
|
||||
struct xfs_perag;
|
||||
struct xfs_bmalloca;
|
||||
|
||||
#ifdef XFS_FILESTREAMS_TRACE
|
||||
#define XFS_FSTRM_KTRACE_INFO 1
|
||||
#define XFS_FSTRM_KTRACE_AGSCAN 2
|
||||
#define XFS_FSTRM_KTRACE_AGPICK1 3
|
||||
#define XFS_FSTRM_KTRACE_AGPICK2 4
|
||||
#define XFS_FSTRM_KTRACE_UPDATE 5
|
||||
#define XFS_FSTRM_KTRACE_FREE 6
|
||||
#define XFS_FSTRM_KTRACE_ITEM_LOOKUP 7
|
||||
#define XFS_FSTRM_KTRACE_ASSOCIATE 8
|
||||
#define XFS_FSTRM_KTRACE_MOVEAG 9
|
||||
#define XFS_FSTRM_KTRACE_ORPHAN 10
|
||||
|
||||
#define XFS_FSTRM_KTRACE_SIZE 16384
|
||||
extern ktrace_t *xfs_filestreams_trace_buf;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocation group filestream associations are tracked with per-ag atomic
|
||||
* counters. These counters allow _xfs_filestream_pick_ag() to tell whether a
|
||||
* particular AG already has active filestreams associated with it. The mount
|
||||
* point's m_peraglock is used to protect these counters from per-ag array
|
||||
* re-allocation during a growfs operation. When xfs_growfs_data_private() is
|
||||
* about to reallocate the array, it calls xfs_filestream_flush() with the
|
||||
* m_peraglock held in write mode.
|
||||
*
|
||||
* Since xfs_mru_cache_flush() guarantees that all the free functions for all
|
||||
* the cache elements have finished executing before it returns, it's safe for
|
||||
* the free functions to use the atomic counters without m_peraglock protection.
|
||||
* This allows the implementation of xfs_fstrm_free_func() to be agnostic about
|
||||
* whether it was called with the m_peraglock held in read mode, write mode or
|
||||
* not held at all. The race condition this addresses is the following:
|
||||
*
|
||||
* - The work queue scheduler fires and pulls a filestream directory cache
|
||||
* element off the LRU end of the cache for deletion, then gets pre-empted.
|
||||
* - A growfs operation grabs the m_peraglock in write mode, flushes all the
|
||||
* remaining items from the cache and reallocates the mount point's per-ag
|
||||
* array, resetting all the counters to zero.
|
||||
* - The work queue thread resumes and calls the free function for the element
|
||||
* it started cleaning up earlier. In the process it decrements the
|
||||
* filestreams counter for an AG that now has no references.
|
||||
*
|
||||
* With a shrinkfs feature, the above scenario could panic the system.
|
||||
*
|
||||
* All other uses of the following macros should be protected by either the
|
||||
* m_peraglock held in read mode, or the cache's internal locking exposed by the
|
||||
* interval between a call to xfs_mru_cache_lookup() and a call to
|
||||
* xfs_mru_cache_done(). In addition, the m_peraglock must be held in read mode
|
||||
* when new elements are added to the cache.
|
||||
*
|
||||
* Combined, these locking rules ensure that no associations will ever exist in
|
||||
* the cache that reference per-ag array elements that have since been
|
||||
* reallocated.
|
||||
*/
|
||||
STATIC_INLINE int
|
||||
xfs_filestream_peek_ag(
|
||||
xfs_mount_t *mp,
|
||||
xfs_agnumber_t agno)
|
||||
{
|
||||
return atomic_read(&mp->m_perag[agno].pagf_fstrms);
|
||||
}
|
||||
|
||||
STATIC_INLINE int
|
||||
xfs_filestream_get_ag(
|
||||
xfs_mount_t *mp,
|
||||
xfs_agnumber_t agno)
|
||||
{
|
||||
return atomic_inc_return(&mp->m_perag[agno].pagf_fstrms);
|
||||
}
|
||||
|
||||
STATIC_INLINE int
|
||||
xfs_filestream_put_ag(
|
||||
xfs_mount_t *mp,
|
||||
xfs_agnumber_t agno)
|
||||
{
|
||||
return atomic_dec_return(&mp->m_perag[agno].pagf_fstrms);
|
||||
}
|
||||
|
||||
/* allocation selection flags */
|
||||
typedef enum xfs_fstrm_alloc {
|
||||
XFS_PICK_USERDATA = 1,
|
||||
XFS_PICK_LOWSPACE = 2,
|
||||
} xfs_fstrm_alloc_t;
|
||||
|
||||
/* prototypes for filestream.c */
|
||||
int xfs_filestream_init(void);
|
||||
void xfs_filestream_uninit(void);
|
||||
int xfs_filestream_mount(struct xfs_mount *mp);
|
||||
void xfs_filestream_unmount(struct xfs_mount *mp);
|
||||
void xfs_filestream_flush(struct xfs_mount *mp);
|
||||
xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip);
|
||||
int xfs_filestream_associate(struct xfs_inode *dip, struct xfs_inode *ip);
|
||||
void xfs_filestream_deassociate(struct xfs_inode *ip);
|
||||
int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp);
|
||||
|
||||
|
||||
/* filestreams for the inode? */
|
||||
STATIC_INLINE int
|
||||
xfs_inode_is_filestream(
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) ||
|
||||
xfs_iflags_test(ip, XFS_IFILESTREAM) ||
|
||||
(ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __XFS_FILESTREAM_H__ */
|
|
@ -66,6 +66,7 @@ struct fsxattr {
|
|||
#define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
|
||||
#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
|
||||
#define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
|
||||
#define XFS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */
|
||||
#define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
|
||||
|
||||
/*
|
||||
|
@ -238,6 +239,7 @@ typedef struct xfs_fsop_resblks {
|
|||
#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */
|
||||
#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */
|
||||
#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */
|
||||
#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "xfs_trans_space.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_rw.h"
|
||||
#include "xfs_filestream.h"
|
||||
|
||||
/*
|
||||
* File system operations
|
||||
|
@ -94,6 +95,8 @@ xfs_fs_geometry(
|
|||
XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) |
|
||||
(XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
|
||||
XFS_FSOP_GEOM_FLAGS_SECTOR : 0) |
|
||||
(xfs_sb_version_haslazysbcount(&mp->m_sb) ?
|
||||
XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) |
|
||||
(XFS_SB_VERSION_HASATTR2(&mp->m_sb) ?
|
||||
XFS_FSOP_GEOM_FLAGS_ATTR2 : 0);
|
||||
geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
|
||||
|
@ -140,6 +143,8 @@ xfs_growfs_data_private(
|
|||
pct = in->imaxpct;
|
||||
if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
|
||||
return XFS_ERROR(EINVAL);
|
||||
if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
|
||||
return error;
|
||||
dpct = pct - mp->m_sb.sb_imax_pct;
|
||||
error = xfs_read_buf(mp, mp->m_ddev_targp,
|
||||
XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
|
||||
|
@ -161,6 +166,7 @@ xfs_growfs_data_private(
|
|||
new = nb - mp->m_sb.sb_dblocks;
|
||||
oagcount = mp->m_sb.sb_agcount;
|
||||
if (nagcount > oagcount) {
|
||||
xfs_filestream_flush(mp);
|
||||
down_write(&mp->m_peraglock);
|
||||
mp->m_perag = kmem_realloc(mp->m_perag,
|
||||
sizeof(xfs_perag_t) * nagcount,
|
||||
|
@ -173,6 +179,7 @@ xfs_growfs_data_private(
|
|||
up_write(&mp->m_peraglock);
|
||||
}
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
|
||||
tp->t_flags |= XFS_TRANS_RESERVE;
|
||||
if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp),
|
||||
XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) {
|
||||
xfs_trans_cancel(tp, 0);
|
||||
|
@ -328,6 +335,7 @@ xfs_growfs_data_private(
|
|||
be32_add(&agf->agf_length, new);
|
||||
ASSERT(be32_to_cpu(agf->agf_length) ==
|
||||
be32_to_cpu(agi->agi_length));
|
||||
xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);
|
||||
/*
|
||||
* Free the new space.
|
||||
*/
|
||||
|
@ -494,8 +502,9 @@ xfs_reserve_blocks(
|
|||
unsigned long s;
|
||||
|
||||
/* If inval is null, report current values and return */
|
||||
|
||||
if (inval == (__uint64_t *)NULL) {
|
||||
if (!outval)
|
||||
return EINVAL;
|
||||
outval->resblks = mp->m_resblks;
|
||||
outval->resblks_avail = mp->m_resblks_avail;
|
||||
return 0;
|
||||
|
@ -558,8 +567,10 @@ retry:
|
|||
}
|
||||
}
|
||||
out:
|
||||
outval->resblks = mp->m_resblks;
|
||||
outval->resblks_avail = mp->m_resblks_avail;
|
||||
if (outval) {
|
||||
outval->resblks = mp->m_resblks;
|
||||
outval->resblks_avail = mp->m_resblks_avail;
|
||||
}
|
||||
XFS_SB_UNLOCK(mp, s);
|
||||
|
||||
if (fdblks_delta) {
|
||||
|
|
|
@ -123,6 +123,7 @@ xfs_ialloc_ag_alloc(
|
|||
int blks_per_cluster; /* fs blocks per inode cluster */
|
||||
xfs_btree_cur_t *cur; /* inode btree cursor */
|
||||
xfs_daddr_t d; /* disk addr of buffer */
|
||||
xfs_agnumber_t agno;
|
||||
int error;
|
||||
xfs_buf_t *fbuf; /* new free inodes' buffer */
|
||||
xfs_dinode_t *free; /* new free inode structure */
|
||||
|
@ -302,15 +303,15 @@ xfs_ialloc_ag_alloc(
|
|||
}
|
||||
be32_add(&agi->agi_count, newlen);
|
||||
be32_add(&agi->agi_freecount, newlen);
|
||||
agno = be32_to_cpu(agi->agi_seqno);
|
||||
down_read(&args.mp->m_peraglock);
|
||||
args.mp->m_perag[be32_to_cpu(agi->agi_seqno)].pagi_freecount += newlen;
|
||||
args.mp->m_perag[agno].pagi_freecount += newlen;
|
||||
up_read(&args.mp->m_peraglock);
|
||||
agi->agi_newino = cpu_to_be32(newino);
|
||||
/*
|
||||
* Insert records describing the new inode chunk into the btree.
|
||||
*/
|
||||
cur = xfs_btree_init_cursor(args.mp, tp, agbp,
|
||||
be32_to_cpu(agi->agi_seqno),
|
||||
cur = xfs_btree_init_cursor(args.mp, tp, agbp, agno,
|
||||
XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
|
||||
for (thisino = newino;
|
||||
thisino < newino + newlen;
|
||||
|
@ -1387,6 +1388,7 @@ xfs_ialloc_read_agi(
|
|||
pag = &mp->m_perag[agno];
|
||||
if (!pag->pagi_init) {
|
||||
pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
|
||||
pag->pagi_count = be32_to_cpu(agi->agi_count);
|
||||
pag->pagi_init = 1;
|
||||
} else {
|
||||
/*
|
||||
|
@ -1410,3 +1412,23 @@ xfs_ialloc_read_agi(
|
|||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in the agi to initialise the per-ag data in the mount structure
|
||||
*/
|
||||
int
|
||||
xfs_ialloc_pagi_init(
|
||||
xfs_mount_t *mp, /* file system mount structure */
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_agnumber_t agno) /* allocation group number */
|
||||
{
|
||||
xfs_buf_t *bp = NULL;
|
||||
int error;
|
||||
|
||||
error = xfs_ialloc_read_agi(mp, tp, agno, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
if (bp)
|
||||
xfs_trans_brelse(tp, bp);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -149,6 +149,16 @@ xfs_ialloc_read_agi(
|
|||
xfs_agnumber_t agno, /* allocation group number */
|
||||
struct xfs_buf **bpp); /* allocation group hdr buf */
|
||||
|
||||
/*
|
||||
* Read in the allocation group header to initialise the per-ag data
|
||||
* in the mount structure
|
||||
*/
|
||||
int
|
||||
xfs_ialloc_pagi_init(
|
||||
struct xfs_mount *mp, /* file system mount structure */
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_agnumber_t agno); /* allocation group number */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __XFS_IALLOC_H__ */
|
||||
|
|
|
@ -48,7 +48,9 @@
|
|||
#include "xfs_dir2_trace.h"
|
||||
#include "xfs_quota.h"
|
||||
#include "xfs_acl.h"
|
||||
#include "xfs_filestream.h"
|
||||
|
||||
#include <linux/log2.h>
|
||||
|
||||
kmem_zone_t *xfs_ifork_zone;
|
||||
kmem_zone_t *xfs_inode_zone;
|
||||
|
@ -643,8 +645,7 @@ xfs_iformat_extents(
|
|||
ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1),
|
||||
ARCH_CONVERT);
|
||||
}
|
||||
xfs_bmap_trace_exlist("xfs_iformat_extents", ip, nex,
|
||||
whichfork);
|
||||
XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
|
||||
if (whichfork != XFS_DATA_FORK ||
|
||||
XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
|
||||
if (unlikely(xfs_check_nostate_extents(
|
||||
|
@ -817,6 +818,8 @@ _xfs_dic2xflags(
|
|||
flags |= XFS_XFLAG_EXTSZINHERIT;
|
||||
if (di_flags & XFS_DIFLAG_NODEFRAG)
|
||||
flags |= XFS_XFLAG_NODEFRAG;
|
||||
if (di_flags & XFS_DIFLAG_FILESTREAM)
|
||||
flags |= XFS_XFLAG_FILESTREAM;
|
||||
}
|
||||
|
||||
return flags;
|
||||
|
@ -1074,6 +1077,11 @@ xfs_iread_extents(
|
|||
* also returns the [locked] bp pointing to the head of the freelist
|
||||
* as ialloc_context. The caller should hold this buffer across
|
||||
* the commit and pass it back into this routine on the second call.
|
||||
*
|
||||
* If we are allocating quota inodes, we do not have a parent inode
|
||||
* to attach to or associate with (i.e. pip == NULL) because they
|
||||
* are not linked into the directory structure - they are attached
|
||||
* directly to the superblock - and so have no parent.
|
||||
*/
|
||||
int
|
||||
xfs_ialloc(
|
||||
|
@ -1099,7 +1107,7 @@ xfs_ialloc(
|
|||
* Call the space management code to pick
|
||||
* the on-disk inode to be allocated.
|
||||
*/
|
||||
error = xfs_dialloc(tp, pip->i_ino, mode, okalloc,
|
||||
error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc,
|
||||
ialloc_context, call_again, &ino);
|
||||
if (error != 0) {
|
||||
return error;
|
||||
|
@ -1150,10 +1158,10 @@ xfs_ialloc(
|
|||
/*
|
||||
* Project ids won't be stored on disk if we are using a version 1 inode.
|
||||
*/
|
||||
if ( (prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
|
||||
if ((prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
|
||||
xfs_bump_ino_vers2(tp, ip);
|
||||
|
||||
if (XFS_INHERIT_GID(pip, vp->v_vfsp)) {
|
||||
if (pip && XFS_INHERIT_GID(pip, vp->v_vfsp)) {
|
||||
ip->i_d.di_gid = pip->i_d.di_gid;
|
||||
if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
|
||||
ip->i_d.di_mode |= S_ISGID;
|
||||
|
@ -1195,8 +1203,16 @@ xfs_ialloc(
|
|||
flags |= XFS_ILOG_DEV;
|
||||
break;
|
||||
case S_IFREG:
|
||||
if (pip && xfs_inode_is_filestream(pip)) {
|
||||
error = xfs_filestream_associate(pip, ip);
|
||||
if (error < 0)
|
||||
return -error;
|
||||
if (!error)
|
||||
xfs_iflags_set(ip, XFS_IFILESTREAM);
|
||||
}
|
||||
/* fall through */
|
||||
case S_IFDIR:
|
||||
if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
|
||||
if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
|
||||
uint di_flags = 0;
|
||||
|
||||
if ((mode & S_IFMT) == S_IFDIR) {
|
||||
|
@ -1233,6 +1249,8 @@ xfs_ialloc(
|
|||
if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) &&
|
||||
xfs_inherit_nodefrag)
|
||||
di_flags |= XFS_DIFLAG_NODEFRAG;
|
||||
if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM)
|
||||
di_flags |= XFS_DIFLAG_FILESTREAM;
|
||||
ip->i_d.di_flags |= di_flags;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
@ -2875,9 +2893,6 @@ xfs_iextents_copy(
|
|||
int copied;
|
||||
xfs_bmbt_rec_t *dest_ep;
|
||||
xfs_bmbt_rec_t *ep;
|
||||
#ifdef XFS_BMAP_TRACE
|
||||
static char fname[] = "xfs_iextents_copy";
|
||||
#endif
|
||||
int i;
|
||||
xfs_ifork_t *ifp;
|
||||
int nrecs;
|
||||
|
@ -2888,7 +2903,7 @@ xfs_iextents_copy(
|
|||
ASSERT(ifp->if_bytes > 0);
|
||||
|
||||
nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
|
||||
xfs_bmap_trace_exlist(fname, ip, nrecs, whichfork);
|
||||
XFS_BMAP_TRACE_EXLIST(ip, nrecs, whichfork);
|
||||
ASSERT(nrecs > 0);
|
||||
|
||||
/*
|
||||
|
@ -4184,7 +4199,7 @@ xfs_iext_realloc_direct(
|
|||
ifp->if_bytes = new_size;
|
||||
return;
|
||||
}
|
||||
if ((new_size & (new_size - 1)) != 0) {
|
||||
if (!is_power_of_2(new_size)){
|
||||
rnew_size = xfs_iroundup(new_size);
|
||||
}
|
||||
if (rnew_size != ifp->if_real_bytes) {
|
||||
|
@ -4207,7 +4222,7 @@ xfs_iext_realloc_direct(
|
|||
*/
|
||||
else {
|
||||
new_size += ifp->if_bytes;
|
||||
if ((new_size & (new_size - 1)) != 0) {
|
||||
if (!is_power_of_2(new_size)) {
|
||||
rnew_size = xfs_iroundup(new_size);
|
||||
}
|
||||
xfs_iext_inline_to_direct(ifp, rnew_size);
|
||||
|
|
|
@ -379,6 +379,7 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
|
|||
#define XFS_ISTALE 0x0010 /* inode has been staled */
|
||||
#define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
|
||||
#define XFS_INEW 0x0040
|
||||
#define XFS_IFILESTREAM 0x0080 /* inode is in a filestream directory */
|
||||
|
||||
/*
|
||||
* Flags for inode locking.
|
||||
|
@ -414,19 +415,22 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
|
|||
* gets a lockdep subclass of 1 and the second lock will have a lockdep
|
||||
* subclass of 0.
|
||||
*
|
||||
* XFS_I[O]LOCK_INUMORDER - for locking several inodes at the some time
|
||||
* XFS_LOCK_INUMORDER - for locking several inodes at the some time
|
||||
* with xfs_lock_inodes(). This flag is used as the starting subclass
|
||||
* and each subsequent lock acquired will increment the subclass by one.
|
||||
* So the first lock acquired will have a lockdep subclass of 2, the
|
||||
* second lock will have a lockdep subclass of 3, and so on.
|
||||
* second lock will have a lockdep subclass of 3, and so on. It is
|
||||
* the responsibility of the class builder to shift this to the correct
|
||||
* portion of the lock_mode lockdep mask.
|
||||
*/
|
||||
#define XFS_LOCK_PARENT 1
|
||||
#define XFS_LOCK_INUMORDER 2
|
||||
|
||||
#define XFS_IOLOCK_SHIFT 16
|
||||
#define XFS_IOLOCK_PARENT (1 << XFS_IOLOCK_SHIFT)
|
||||
#define XFS_IOLOCK_INUMORDER (2 << XFS_IOLOCK_SHIFT)
|
||||
#define XFS_IOLOCK_PARENT (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)
|
||||
|
||||
#define XFS_ILOCK_SHIFT 24
|
||||
#define XFS_ILOCK_PARENT (1 << XFS_ILOCK_SHIFT)
|
||||
#define XFS_ILOCK_INUMORDER (2 << XFS_ILOCK_SHIFT)
|
||||
#define XFS_ILOCK_PARENT (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT)
|
||||
|
||||
#define XFS_IOLOCK_DEP_MASK 0x00ff0000
|
||||
#define XFS_ILOCK_DEP_MASK 0xff000000
|
||||
|
|
|
@ -451,19 +451,14 @@ xfs_iomap_write_direct(
|
|||
return XFS_ERROR(error);
|
||||
|
||||
rt = XFS_IS_REALTIME_INODE(ip);
|
||||
if (unlikely(rt)) {
|
||||
if (!(extsz = ip->i_d.di_extsize))
|
||||
extsz = mp->m_sb.sb_rextsize;
|
||||
} else {
|
||||
extsz = ip->i_d.di_extsize;
|
||||
}
|
||||
extsz = xfs_get_extsz_hint(ip);
|
||||
|
||||
isize = ip->i_size;
|
||||
if (io->io_new_size > isize)
|
||||
isize = io->io_new_size;
|
||||
|
||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
|
||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
|
||||
if ((offset + count) > isize) {
|
||||
error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
|
||||
&last_fsb);
|
||||
|
@ -489,13 +484,13 @@ xfs_iomap_write_direct(
|
|||
if (unlikely(rt)) {
|
||||
resrtextents = qblocks = resaligned;
|
||||
resrtextents /= mp->m_sb.sb_rextsize;
|
||||
resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
|
||||
quota_flag = XFS_QMOPT_RES_RTBLKS;
|
||||
} else {
|
||||
resrtextents = 0;
|
||||
resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
|
||||
quota_flag = XFS_QMOPT_RES_RTBLKS;
|
||||
} else {
|
||||
resrtextents = 0;
|
||||
resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
|
||||
quota_flag = XFS_QMOPT_RES_REGBLKS;
|
||||
}
|
||||
quota_flag = XFS_QMOPT_RES_REGBLKS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and setup the transaction
|
||||
|
@ -666,13 +661,7 @@ xfs_iomap_write_delay(
|
|||
if (error)
|
||||
return XFS_ERROR(error);
|
||||
|
||||
if (XFS_IS_REALTIME_INODE(ip)) {
|
||||
if (!(extsz = ip->i_d.di_extsize))
|
||||
extsz = mp->m_sb.sb_rextsize;
|
||||
} else {
|
||||
extsz = ip->i_d.di_extsize;
|
||||
}
|
||||
|
||||
extsz = xfs_get_extsz_hint(ip);
|
||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
|
||||
retry:
|
||||
|
@ -788,18 +777,12 @@ xfs_iomap_write_allocate(
|
|||
nimaps = 0;
|
||||
while (nimaps == 0) {
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
|
||||
tp->t_flags |= XFS_TRANS_RESERVE;
|
||||
nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
|
||||
error = xfs_trans_reserve(tp, nres,
|
||||
XFS_WRITE_LOG_RES(mp),
|
||||
0, XFS_TRANS_PERM_LOG_RES,
|
||||
XFS_WRITE_LOG_COUNT);
|
||||
if (error == ENOSPC) {
|
||||
error = xfs_trans_reserve(tp, 0,
|
||||
XFS_WRITE_LOG_RES(mp),
|
||||
0,
|
||||
XFS_TRANS_PERM_LOG_RES,
|
||||
XFS_WRITE_LOG_COUNT);
|
||||
}
|
||||
if (error) {
|
||||
xfs_trans_cancel(tp, 0);
|
||||
return XFS_ERROR(error);
|
||||
|
@ -917,8 +900,8 @@ xfs_iomap_write_unwritten(
|
|||
* from unwritten to real. Do allocations in a loop until
|
||||
* we have covered the range passed in.
|
||||
*/
|
||||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
|
||||
tp->t_flags |= XFS_TRANS_RESERVE;
|
||||
error = xfs_trans_reserve(tp, resblks,
|
||||
XFS_WRITE_LOG_RES(mp), 0,
|
||||
XFS_TRANS_PERM_LOG_RES,
|
||||
|
|
|
@ -202,6 +202,16 @@ xfs_bulkstat_one_dinode(
|
|||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_bulkstat_one_fmt(
|
||||
void __user *ubuffer,
|
||||
const xfs_bstat_t *buffer)
|
||||
{
|
||||
if (copy_to_user(ubuffer, buffer, sizeof(*buffer)))
|
||||
return -EFAULT;
|
||||
return sizeof(*buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return stat information for one inode.
|
||||
* Return 0 if ok, else errno.
|
||||
|
@ -221,6 +231,7 @@ xfs_bulkstat_one(
|
|||
xfs_bstat_t *buf; /* return buffer */
|
||||
int error = 0; /* error value */
|
||||
xfs_dinode_t *dip; /* dinode inode pointer */
|
||||
bulkstat_one_fmt_pf formatter = private_data ? : xfs_bulkstat_one_fmt;
|
||||
|
||||
dip = (xfs_dinode_t *)dibuff;
|
||||
*stat = BULKSTAT_RV_NOTHING;
|
||||
|
@ -243,14 +254,15 @@ xfs_bulkstat_one(
|
|||
xfs_bulkstat_one_dinode(mp, ino, dip, buf);
|
||||
}
|
||||
|
||||
if (copy_to_user(buffer, buf, sizeof(*buf))) {
|
||||
error = formatter(buffer, buf);
|
||||
if (error < 0) {
|
||||
error = EFAULT;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
*stat = BULKSTAT_RV_DIDONE;
|
||||
if (ubused)
|
||||
*ubused = sizeof(*buf);
|
||||
*ubused = error;
|
||||
|
||||
out_free:
|
||||
kmem_free(buf, sizeof(*buf));
|
||||
|
@ -748,6 +760,19 @@ xfs_bulkstat_single(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xfs_inumbers_fmt(
|
||||
void __user *ubuffer, /* buffer to write to */
|
||||
const xfs_inogrp_t *buffer, /* buffer to read from */
|
||||
long count, /* # of elements to read */
|
||||
long *written) /* # of bytes written */
|
||||
{
|
||||
if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer)))
|
||||
return -EFAULT;
|
||||
*written = count * sizeof(*buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return inode number table for the filesystem.
|
||||
*/
|
||||
|
@ -756,7 +781,8 @@ xfs_inumbers(
|
|||
xfs_mount_t *mp, /* mount point for filesystem */
|
||||
xfs_ino_t *lastino, /* last inode returned */
|
||||
int *count, /* size of buffer/count returned */
|
||||
xfs_inogrp_t __user *ubuffer)/* buffer with inode descriptions */
|
||||
void __user *ubuffer,/* buffer with inode descriptions */
|
||||
inumbers_fmt_pf formatter)
|
||||
{
|
||||
xfs_buf_t *agbp;
|
||||
xfs_agino_t agino;
|
||||
|
@ -835,12 +861,12 @@ xfs_inumbers(
|
|||
bufidx++;
|
||||
left--;
|
||||
if (bufidx == bcount) {
|
||||
if (copy_to_user(ubuffer, buffer,
|
||||
bufidx * sizeof(*buffer))) {
|
||||
long written;
|
||||
if (formatter(ubuffer, buffer, bufidx, &written)) {
|
||||
error = XFS_ERROR(EFAULT);
|
||||
break;
|
||||
}
|
||||
ubuffer += bufidx;
|
||||
ubuffer += written;
|
||||
*count += bufidx;
|
||||
bufidx = 0;
|
||||
}
|
||||
|
@ -862,8 +888,8 @@ xfs_inumbers(
|
|||
}
|
||||
if (!error) {
|
||||
if (bufidx) {
|
||||
if (copy_to_user(ubuffer, buffer,
|
||||
bufidx * sizeof(*buffer)))
|
||||
long written;
|
||||
if (formatter(ubuffer, buffer, bufidx, &written))
|
||||
error = XFS_ERROR(EFAULT);
|
||||
else
|
||||
*count += bufidx;
|
||||
|
|
|
@ -69,6 +69,10 @@ xfs_bulkstat_single(
|
|||
char __user *buffer,
|
||||
int *done);
|
||||
|
||||
typedef int (*bulkstat_one_fmt_pf)( /* used size in bytes or negative error */
|
||||
void __user *ubuffer, /* buffer to write to */
|
||||
const xfs_bstat_t *buffer); /* buffer to read from */
|
||||
|
||||
int
|
||||
xfs_bulkstat_one(
|
||||
xfs_mount_t *mp,
|
||||
|
@ -86,11 +90,25 @@ xfs_internal_inum(
|
|||
xfs_mount_t *mp,
|
||||
xfs_ino_t ino);
|
||||
|
||||
typedef int (*inumbers_fmt_pf)(
|
||||
void __user *ubuffer, /* buffer to write to */
|
||||
const xfs_inogrp_t *buffer, /* buffer to read from */
|
||||
long count, /* # of elements to read */
|
||||
long *written); /* # of bytes written */
|
||||
|
||||
int
|
||||
xfs_inumbers_fmt(
|
||||
void __user *ubuffer, /* buffer to write to */
|
||||
const xfs_inogrp_t *buffer, /* buffer to read from */
|
||||
long count, /* # of elements to read */
|
||||
long *written); /* # of bytes written */
|
||||
|
||||
int /* error status */
|
||||
xfs_inumbers(
|
||||
xfs_mount_t *mp, /* mount point for filesystem */
|
||||
xfs_ino_t *last, /* last inode returned */
|
||||
int *count, /* size of buffer/count returned */
|
||||
xfs_inogrp_t __user *buffer);/* buffer with inode info */
|
||||
void __user *buffer, /* buffer with inode info */
|
||||
inumbers_fmt_pf formatter);
|
||||
|
||||
#endif /* __XFS_ITABLE_H__ */
|
||||
|
|
|
@ -817,10 +817,8 @@ xfs_log_need_covered(xfs_mount_t *mp)
|
|||
SPLDECL(s);
|
||||
int needed = 0, gen;
|
||||
xlog_t *log = mp->m_log;
|
||||
bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
|
||||
|
||||
if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
|
||||
(vfsp->vfs_flag & VFS_RDONLY))
|
||||
if (!xfs_fs_writable(mp))
|
||||
return 0;
|
||||
|
||||
s = LOG_LOCK(log);
|
||||
|
@ -967,14 +965,16 @@ xlog_iodone(xfs_buf_t *bp)
|
|||
} else if (iclog->ic_state & XLOG_STATE_IOERROR) {
|
||||
aborted = XFS_LI_ABORTED;
|
||||
}
|
||||
|
||||
/* log I/O is always issued ASYNC */
|
||||
ASSERT(XFS_BUF_ISASYNC(bp));
|
||||
xlog_state_done_syncing(iclog, aborted);
|
||||
if (!(XFS_BUF_ISASYNC(bp))) {
|
||||
/*
|
||||
* Corresponding psema() will be done in bwrite(). If we don't
|
||||
* vsema() here, panic.
|
||||
*/
|
||||
XFS_BUF_V_IODONESEMA(bp);
|
||||
}
|
||||
/*
|
||||
* do not reference the buffer (bp) here as we could race
|
||||
* with it being freed after writing the unmount record to the
|
||||
* log.
|
||||
*/
|
||||
|
||||
} /* xlog_iodone */
|
||||
|
||||
/*
|
||||
|
@ -1199,11 +1199,18 @@ xlog_alloc_log(xfs_mount_t *mp,
|
|||
*iclogp = (xlog_in_core_t *)
|
||||
kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
|
||||
iclog = *iclogp;
|
||||
iclog->hic_data = (xlog_in_core_2_t *)
|
||||
kmem_zalloc(iclogsize, KM_SLEEP | KM_LARGE);
|
||||
|
||||
iclog->ic_prev = prev_iclog;
|
||||
prev_iclog = iclog;
|
||||
|
||||
bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
|
||||
if (!XFS_BUF_CPSEMA(bp))
|
||||
ASSERT(0);
|
||||
XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
|
||||
XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
|
||||
XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
|
||||
iclog->ic_bp = bp;
|
||||
iclog->hic_data = bp->b_addr;
|
||||
|
||||
log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
|
||||
|
||||
head = &iclog->ic_header;
|
||||
|
@ -1216,11 +1223,6 @@ xlog_alloc_log(xfs_mount_t *mp,
|
|||
INT_SET(head->h_fmt, ARCH_CONVERT, XLOG_FMT);
|
||||
memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
|
||||
|
||||
bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
|
||||
XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
|
||||
XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
|
||||
XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
|
||||
iclog->ic_bp = bp;
|
||||
|
||||
iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
|
||||
iclog->ic_state = XLOG_STATE_ACTIVE;
|
||||
|
@ -1432,7 +1434,7 @@ xlog_sync(xlog_t *log,
|
|||
} else {
|
||||
iclog->ic_bwritecnt = 1;
|
||||
}
|
||||
XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count);
|
||||
XFS_BUF_SET_COUNT(bp, count);
|
||||
XFS_BUF_SET_FSPRIVATE(bp, iclog); /* save for later */
|
||||
XFS_BUF_ZEROFLAGS(bp);
|
||||
XFS_BUF_BUSY(bp);
|
||||
|
@ -1528,7 +1530,6 @@ xlog_dealloc_log(xlog_t *log)
|
|||
}
|
||||
#endif
|
||||
next_iclog = iclog->ic_next;
|
||||
kmem_free(iclog->hic_data, log->l_iclog_size);
|
||||
kmem_free(iclog, sizeof(xlog_in_core_t));
|
||||
iclog = next_iclog;
|
||||
}
|
||||
|
|
|
@ -927,6 +927,14 @@ xlog_find_tail(
|
|||
ASSIGN_ANY_LSN_HOST(log->l_last_sync_lsn, log->l_curr_cycle,
|
||||
after_umount_blk);
|
||||
*tail_blk = after_umount_blk;
|
||||
|
||||
/*
|
||||
* Note that the unmount was clean. If the unmount
|
||||
* was not clean, we need to know this to rebuild the
|
||||
* superblock counters from the perag headers if we
|
||||
* have a filesystem using non-persistent counters.
|
||||
*/
|
||||
log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -202,6 +202,27 @@ xfs_mount_free(
|
|||
kmem_free(mp, sizeof(xfs_mount_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check size of device based on the (data/realtime) block count.
|
||||
* Note: this check is used by the growfs code as well as mount.
|
||||
*/
|
||||
int
|
||||
xfs_sb_validate_fsb_count(
|
||||
xfs_sb_t *sbp,
|
||||
__uint64_t nblocks)
|
||||
{
|
||||
ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
|
||||
ASSERT(sbp->sb_blocklog >= BBSHIFT);
|
||||
|
||||
#if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */
|
||||
if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
|
||||
return E2BIG;
|
||||
#else /* Limited by UINT_MAX of sectors */
|
||||
if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
|
||||
return E2BIG;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the validity of the SB found.
|
||||
|
@ -284,18 +305,8 @@ xfs_mount_validate_sb(
|
|||
return XFS_ERROR(EFSCORRUPTED);
|
||||
}
|
||||
|
||||
ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
|
||||
ASSERT(sbp->sb_blocklog >= BBSHIFT);
|
||||
|
||||
#if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */
|
||||
if (unlikely(
|
||||
(sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
|
||||
(sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
|
||||
#else /* Limited by UINT_MAX of sectors */
|
||||
if (unlikely(
|
||||
(sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
|
||||
(sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
|
||||
#endif
|
||||
if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
|
||||
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);
|
||||
|
@ -632,6 +643,64 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
|
|||
sbp->sb_inopblock);
|
||||
mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_initialize_perag_data
|
||||
*
|
||||
* Read in each per-ag structure so we can count up the number of
|
||||
* allocated inodes, free inodes and used filesystem blocks as this
|
||||
* information is no longer persistent in the superblock. Once we have
|
||||
* this information, write it into the in-core superblock structure.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
|
||||
{
|
||||
xfs_agnumber_t index;
|
||||
xfs_perag_t *pag;
|
||||
xfs_sb_t *sbp = &mp->m_sb;
|
||||
uint64_t ifree = 0;
|
||||
uint64_t ialloc = 0;
|
||||
uint64_t bfree = 0;
|
||||
uint64_t bfreelst = 0;
|
||||
uint64_t btree = 0;
|
||||
int error;
|
||||
int s;
|
||||
|
||||
for (index = 0; index < agcount; index++) {
|
||||
/*
|
||||
* read the agf, then the agi. This gets us
|
||||
* all the inforamtion we need and populates the
|
||||
* per-ag structures for us.
|
||||
*/
|
||||
error = xfs_alloc_pagf_init(mp, NULL, index, 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xfs_ialloc_pagi_init(mp, NULL, index);
|
||||
if (error)
|
||||
return error;
|
||||
pag = &mp->m_perag[index];
|
||||
ifree += pag->pagi_freecount;
|
||||
ialloc += pag->pagi_count;
|
||||
bfree += pag->pagf_freeblks;
|
||||
bfreelst += pag->pagf_flcount;
|
||||
btree += pag->pagf_btreeblks;
|
||||
}
|
||||
/*
|
||||
* Overwrite incore superblock counters with just-read data
|
||||
*/
|
||||
s = XFS_SB_LOCK(mp);
|
||||
sbp->sb_ifree = ifree;
|
||||
sbp->sb_icount = ialloc;
|
||||
sbp->sb_fdblocks = bfree + bfreelst + btree;
|
||||
XFS_SB_UNLOCK(mp, s);
|
||||
|
||||
/* Fixup the per-cpu counters as well. */
|
||||
xfs_icsb_reinit_counters(mp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_mountfs
|
||||
*
|
||||
|
@ -656,7 +725,7 @@ xfs_mountfs(
|
|||
bhv_vnode_t *rvp = NULL;
|
||||
int readio_log, writeio_log;
|
||||
xfs_daddr_t d;
|
||||
__uint64_t ret64;
|
||||
__uint64_t resblks;
|
||||
__int64_t update_flags;
|
||||
uint quotamount, quotaflags;
|
||||
int agno;
|
||||
|
@ -773,6 +842,7 @@ xfs_mountfs(
|
|||
*/
|
||||
if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
|
||||
(mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
|
||||
__uint64_t ret64;
|
||||
if (xfs_uuid_mount(mp)) {
|
||||
error = XFS_ERROR(EINVAL);
|
||||
goto error1;
|
||||
|
@ -975,6 +1045,34 @@ xfs_mountfs(
|
|||
goto error2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the log is mounted, we know if it was an unclean shutdown or
|
||||
* not. If it was, with the first phase of recovery has completed, we
|
||||
* have consistent AG blocks on disk. We have not recovered EFIs yet,
|
||||
* but they are recovered transactionally in the second recovery phase
|
||||
* later.
|
||||
*
|
||||
* Hence we can safely re-initialise incore superblock counters from
|
||||
* the per-ag data. These may not be correct if the filesystem was not
|
||||
* cleanly unmounted, so we need to wait for recovery to finish before
|
||||
* doing this.
|
||||
*
|
||||
* If the filesystem was cleanly unmounted, then we can trust the
|
||||
* values in the superblock to be correct and we don't need to do
|
||||
* anything here.
|
||||
*
|
||||
* If we are currently making the filesystem, the initialisation will
|
||||
* fail as the perag data is in an undefined state.
|
||||
*/
|
||||
|
||||
if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
|
||||
!XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
|
||||
!mp->m_sb.sb_inprogress) {
|
||||
error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
|
||||
if (error) {
|
||||
goto error2;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Get and sanity-check the root inode.
|
||||
* Save the pointer to it in the mount structure.
|
||||
|
@ -1044,6 +1142,23 @@ xfs_mountfs(
|
|||
if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags)))
|
||||
goto error4;
|
||||
|
||||
/*
|
||||
* Now we are mounted, reserve a small amount of unused space for
|
||||
* privileged transactions. This is needed so that transaction
|
||||
* space required for critical operations can dip into this pool
|
||||
* when at ENOSPC. This is needed for operations like create with
|
||||
* attr, unwritten extent conversion at ENOSPC, etc. Data allocations
|
||||
* are not allowed to use this reserved space.
|
||||
*
|
||||
* We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
|
||||
* This may drive us straight to ENOSPC on mount, but that implies
|
||||
* we were already there on the last unmount.
|
||||
*/
|
||||
resblks = mp->m_sb.sb_dblocks;
|
||||
do_div(resblks, 20);
|
||||
resblks = min_t(__uint64_t, resblks, 1024);
|
||||
xfs_reserve_blocks(mp, &resblks, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
error4:
|
||||
|
@ -1083,7 +1198,19 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
|
|||
#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
|
||||
int64_t fsid;
|
||||
#endif
|
||||
__uint64_t resblks;
|
||||
|
||||
/*
|
||||
* We can potentially deadlock here if we have an inode cluster
|
||||
* that has been freed has it's buffer still pinned in memory because
|
||||
* the transaction is still sitting in a iclog. The stale inodes
|
||||
* on that buffer will have their flush locks held until the
|
||||
* transaction hits the disk and the callbacks run. the inode
|
||||
* flush takes the flush lock unconditionally and with nothing to
|
||||
* push out the iclog we will never get that unlocked. hence we
|
||||
* need to force the log first.
|
||||
*/
|
||||
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
|
||||
xfs_iflush_all(mp);
|
||||
|
||||
XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
|
||||
|
@ -1100,10 +1227,26 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
|
|||
xfs_binval(mp->m_rtdev_targp);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* lazy superblock counting because it trusts the incore superblock
|
||||
* counters to be aboslutely correct on clean unmount.
|
||||
*
|
||||
* We don't bother correcting this elsewhere for lazy superblock
|
||||
* counting because on mount of an unclean filesystem we reconstruct the
|
||||
* correct counter value and this is irrelevant.
|
||||
*
|
||||
* For non-lazy counter filesystems, this doesn't matter at all because
|
||||
* we only every apply deltas to the superblock and hence the incore
|
||||
* value does not matter....
|
||||
*/
|
||||
resblks = 0;
|
||||
xfs_reserve_blocks(mp, &resblks, NULL);
|
||||
|
||||
xfs_log_sbcount(mp, 1);
|
||||
xfs_unmountfs_writesb(mp);
|
||||
|
||||
xfs_unmountfs_wait(mp); /* wait for async bufs */
|
||||
|
||||
xfs_log_unmount(mp); /* Done! No more fs ops. */
|
||||
|
||||
xfs_freesb(mp);
|
||||
|
@ -1149,6 +1292,62 @@ xfs_unmountfs_wait(xfs_mount_t *mp)
|
|||
xfs_wait_buftarg(mp->m_ddev_targp);
|
||||
}
|
||||
|
||||
int
|
||||
xfs_fs_writable(xfs_mount_t *mp)
|
||||
{
|
||||
bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
|
||||
|
||||
return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
|
||||
(vfsp->vfs_flag & VFS_RDONLY));
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_log_sbcount
|
||||
*
|
||||
* Called either periodically to keep the on disk superblock values
|
||||
* roughly up to date or from unmount to make sure the values are
|
||||
* correct on a clean unmount.
|
||||
*
|
||||
* Note this code can be called during the process of freezing, so
|
||||
* we may need to use the transaction allocator which does not not
|
||||
* block when the transaction subsystem is in its frozen state.
|
||||
*/
|
||||
int
|
||||
xfs_log_sbcount(
|
||||
xfs_mount_t *mp,
|
||||
uint sync)
|
||||
{
|
||||
xfs_trans_t *tp;
|
||||
int error;
|
||||
|
||||
if (!xfs_fs_writable(mp))
|
||||
return 0;
|
||||
|
||||
xfs_icsb_sync_counters(mp);
|
||||
|
||||
/*
|
||||
* we don't need to do this if we are updating the superblock
|
||||
* counters on every modification.
|
||||
*/
|
||||
if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
|
||||
return 0;
|
||||
|
||||
tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT);
|
||||
error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
|
||||
XFS_DEFAULT_LOG_COUNT);
|
||||
if (error) {
|
||||
xfs_trans_cancel(tp, 0);
|
||||
return error;
|
||||
}
|
||||
|
||||
xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
|
||||
if (sync)
|
||||
xfs_trans_set_sync(tp);
|
||||
xfs_trans_commit(tp, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xfs_unmountfs_writesb(xfs_mount_t *mp)
|
||||
{
|
||||
|
@ -1160,16 +1359,15 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
|
|||
* skip superblock write if fs is read-only, or
|
||||
* if we are doing a forced umount.
|
||||
*/
|
||||
sbp = xfs_getsb(mp, 0);
|
||||
if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY ||
|
||||
XFS_FORCED_SHUTDOWN(mp))) {
|
||||
|
||||
xfs_icsb_sync_counters(mp);
|
||||
sbp = xfs_getsb(mp, 0);
|
||||
sb = XFS_BUF_TO_SBP(sbp);
|
||||
|
||||
/*
|
||||
* mark shared-readonly if desired
|
||||
*/
|
||||
sb = XFS_BUF_TO_SBP(sbp);
|
||||
if (mp->m_mk_sharedro) {
|
||||
if (!(sb->sb_flags & XFS_SBF_READONLY))
|
||||
sb->sb_flags |= XFS_SBF_READONLY;
|
||||
|
@ -1178,6 +1376,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
|
|||
xfs_fs_cmn_err(CE_NOTE, mp,
|
||||
"Unmounting, marking shared read-only");
|
||||
}
|
||||
|
||||
XFS_BUF_UNDONE(sbp);
|
||||
XFS_BUF_UNREAD(sbp);
|
||||
XFS_BUF_UNDELAYWRITE(sbp);
|
||||
|
@ -1192,8 +1391,8 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
|
|||
mp, sbp, XFS_BUF_ADDR(sbp));
|
||||
if (error && mp->m_mk_sharedro)
|
||||
xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly");
|
||||
xfs_buf_relse(sbp);
|
||||
}
|
||||
xfs_buf_relse(sbp);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ struct xfs_bmbt_irec;
|
|||
struct xfs_bmap_free;
|
||||
struct xfs_extdelta;
|
||||
struct xfs_swapext;
|
||||
struct xfs_mru_cache;
|
||||
|
||||
extern struct bhv_vfsops xfs_vfsops;
|
||||
extern struct bhv_vnodeops xfs_vnodeops;
|
||||
|
@ -424,17 +425,18 @@ typedef struct xfs_mount {
|
|||
struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */
|
||||
struct mutex m_icsb_mutex; /* balancer sync lock */
|
||||
#endif
|
||||
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
|
||||
} xfs_mount_t;
|
||||
|
||||
/*
|
||||
* Flags for m_flags.
|
||||
*/
|
||||
#define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops
|
||||
#define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops
|
||||
must be synchronous except
|
||||
for space allocations */
|
||||
#define XFS_MOUNT_INO64 (1ULL << 1)
|
||||
#define XFS_MOUNT_INO64 (1ULL << 1)
|
||||
/* (1ULL << 2) -- currently unused */
|
||||
/* (1ULL << 3) -- currently unused */
|
||||
#define XFS_MOUNT_WAS_CLEAN (1ULL << 3)
|
||||
#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
|
||||
operations, typically for
|
||||
disk errors in metadata */
|
||||
|
@ -463,6 +465,8 @@ typedef struct xfs_mount {
|
|||
* I/O size in stat() */
|
||||
#define XFS_MOUNT_NO_PERCPU_SB (1ULL << 23) /* don't use per-cpu superblock
|
||||
counters */
|
||||
#define XFS_MOUNT_FILESTREAMS (1ULL << 24) /* enable the filestreams
|
||||
allocator */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -511,6 +515,8 @@ xfs_preferred_iosize(xfs_mount_t *mp)
|
|||
|
||||
#define XFS_MAXIOFFSET(mp) ((mp)->m_maxioffset)
|
||||
|
||||
#define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \
|
||||
((mp)->m_flags & XFS_MOUNT_WAS_CLEAN)
|
||||
#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
|
||||
#define xfs_force_shutdown(m,f) \
|
||||
bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
|
||||
|
@ -602,6 +608,7 @@ typedef struct xfs_mod_sb {
|
|||
|
||||
extern xfs_mount_t *xfs_mount_init(void);
|
||||
extern void xfs_mod_sb(xfs_trans_t *, __int64_t);
|
||||
extern int xfs_log_sbcount(xfs_mount_t *, uint);
|
||||
extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
|
||||
extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int);
|
||||
extern void xfs_mountfs_check_barriers(xfs_mount_t *mp);
|
||||
|
@ -618,12 +625,14 @@ extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
|
|||
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
|
||||
extern int xfs_readsb(xfs_mount_t *, int);
|
||||
extern void xfs_freesb(xfs_mount_t *);
|
||||
extern int xfs_fs_writable(xfs_mount_t *);
|
||||
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
|
||||
extern int xfs_syncsub(xfs_mount_t *, int, int *);
|
||||
extern int xfs_sync_inodes(xfs_mount_t *, int, int *);
|
||||
extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
|
||||
xfs_agnumber_t);
|
||||
extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
|
||||
extern int xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
|
||||
|
||||
extern struct xfs_dmops xfs_dmcore_stub;
|
||||
extern struct xfs_qmops xfs_qmcore_stub;
|
||||
|
|
|
@ -0,0 +1,608 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "xfs.h"
|
||||
#include "xfs_mru_cache.h"
|
||||
|
||||
/*
|
||||
* The MRU Cache data structure consists of a data store, an array of lists and
|
||||
* a lock to protect its internal state. At initialisation time, the client
|
||||
* supplies an element lifetime in milliseconds and a group count, as well as a
|
||||
* function pointer to call when deleting elements. A data structure for
|
||||
* queueing up work in the form of timed callbacks is also included.
|
||||
*
|
||||
* The group count controls how many lists are created, and thereby how finely
|
||||
* the elements are grouped in time. When reaping occurs, all the elements in
|
||||
* all the lists whose time has expired are deleted.
|
||||
*
|
||||
* To give an example of how this works in practice, consider a client that
|
||||
* initialises an MRU Cache with a lifetime of ten seconds and a group count of
|
||||
* five. Five internal lists will be created, each representing a two second
|
||||
* period in time. When the first element is added, time zero for the data
|
||||
* structure is initialised to the current time.
|
||||
*
|
||||
* All the elements added in the first two seconds are appended to the first
|
||||
* list. Elements added in the third second go into the second list, and so on.
|
||||
* If an element is accessed at any point, it is removed from its list and
|
||||
* inserted at the head of the current most-recently-used list.
|
||||
*
|
||||
* The reaper function will have nothing to do until at least twelve seconds
|
||||
* have elapsed since the first element was added. The reason for this is that
|
||||
* if it were called at t=11s, there could be elements in the first list that
|
||||
* have only been inactive for nine seconds, so it still does nothing. If it is
|
||||
* called anywhere between t=12 and t=14 seconds, it will delete all the
|
||||
* elements that remain in the first list. It's therefore possible for elements
|
||||
* to remain in the data store even after they've been inactive for up to
|
||||
* (t + t/g) seconds, where t is the inactive element lifetime and g is the
|
||||
* number of groups.
|
||||
*
|
||||
* The above example assumes that the reaper function gets called at least once
|
||||
* every (t/g) seconds. If it is called less frequently, unused elements will
|
||||
* accumulate in the reap list until the reaper function is eventually called.
|
||||
* The current implementation uses work queue callbacks to carefully time the
|
||||
* reaper function calls, so this should happen rarely, if at all.
|
||||
*
|
||||
* From a design perspective, the primary reason for the choice of a list array
|
||||
* representing discrete time intervals is that it's only practical to reap
|
||||
* expired elements in groups of some appreciable size. This automatically
|
||||
* introduces a granularity to element lifetimes, so there's no point storing an
|
||||
* individual timeout with each element that specifies a more precise reap time.
|
||||
* The bonus is a saving of sizeof(long) bytes of memory per element stored.
|
||||
*
|
||||
* The elements could have been stored in just one list, but an array of
|
||||
* counters or pointers would need to be maintained to allow them to be divided
|
||||
* up into discrete time groups. More critically, the process of touching or
|
||||
* removing an element would involve walking large portions of the entire list,
|
||||
* which would have a detrimental effect on performance. The additional memory
|
||||
* requirement for the array of list heads is minimal.
|
||||
*
|
||||
* When an element is touched or deleted, it needs to be removed from its
|
||||
* current list. Doubly linked lists are used to make the list maintenance
|
||||
* portion of these operations O(1). Since reaper timing can be imprecise,
|
||||
* inserts and lookups can occur when there are no free lists available. When
|
||||
* this happens, all the elements on the LRU list need to be migrated to the end
|
||||
* of the reap list. To keep the list maintenance portion of these operations
|
||||
* O(1) also, list tails need to be accessible without walking the entire list.
|
||||
* This is the reason why doubly linked list heads are used.
|
||||
*/
|
||||
|
||||
/*
|
||||
* An MRU Cache is a dynamic data structure that stores its elements in a way
|
||||
* that allows efficient lookups, but also groups them into discrete time
|
||||
* intervals based on insertion time. This allows elements to be efficiently
|
||||
* and automatically reaped after a fixed period of inactivity.
|
||||
*
|
||||
* When a client data pointer is stored in the MRU Cache it needs to be added to
|
||||
* both the data store and to one of the lists. It must also be possible to
|
||||
* access each of these entries via the other, i.e. to:
|
||||
*
|
||||
* a) Walk a list, removing the corresponding data store entry for each item.
|
||||
* b) Look up a data store entry, then access its list entry directly.
|
||||
*
|
||||
* To achieve both of these goals, each entry must contain both a list entry and
|
||||
* a key, in addition to the user's data pointer. Note that it's not a good
|
||||
* idea to have the client embed one of these structures at the top of their own
|
||||
* data structure, because inserting the same item more than once would most
|
||||
* likely result in a loop in one of the lists. That's a sure-fire recipe for
|
||||
* an infinite loop in the code.
|
||||
*/
|
||||
typedef struct xfs_mru_cache_elem
|
||||
{
|
||||
struct list_head list_node;
|
||||
unsigned long key;
|
||||
void *value;
|
||||
} xfs_mru_cache_elem_t;
|
||||
|
||||
static kmem_zone_t *xfs_mru_elem_zone;
|
||||
static struct workqueue_struct *xfs_mru_reap_wq;
|
||||
|
||||
/*
|
||||
* When inserting, destroying or reaping, it's first necessary to update the
|
||||
* lists relative to a particular time. In the case of destroying, that time
|
||||
* will be well in the future to ensure that all items are moved to the reap
|
||||
* list. In all other cases though, the time will be the current time.
|
||||
*
|
||||
* This function enters a loop, moving the contents of the LRU list to the reap
|
||||
* list again and again until either a) the lists are all empty, or b) time zero
|
||||
* has been advanced sufficiently to be within the immediate element lifetime.
|
||||
*
|
||||
* Case a) above is detected by counting how many groups are migrated and
|
||||
* stopping when they've all been moved. Case b) is detected by monitoring the
|
||||
* time_zero field, which is updated as each group is migrated.
|
||||
*
|
||||
* The return value is the earliest time that more migration could be needed, or
|
||||
* zero if there's no need to schedule more work because the lists are empty.
|
||||
*/
|
||||
STATIC unsigned long
|
||||
_xfs_mru_cache_migrate(
|
||||
xfs_mru_cache_t *mru,
|
||||
unsigned long now)
|
||||
{
|
||||
unsigned int grp;
|
||||
unsigned int migrated = 0;
|
||||
struct list_head *lru_list;
|
||||
|
||||
/* Nothing to do if the data store is empty. */
|
||||
if (!mru->time_zero)
|
||||
return 0;
|
||||
|
||||
/* While time zero is older than the time spanned by all the lists. */
|
||||
while (mru->time_zero <= now - mru->grp_count * mru->grp_time) {
|
||||
|
||||
/*
|
||||
* If the LRU list isn't empty, migrate its elements to the tail
|
||||
* of the reap list.
|
||||
*/
|
||||
lru_list = mru->lists + mru->lru_grp;
|
||||
if (!list_empty(lru_list))
|
||||
list_splice_init(lru_list, mru->reap_list.prev);
|
||||
|
||||
/*
|
||||
* Advance the LRU group number, freeing the old LRU list to
|
||||
* become the new MRU list; advance time zero accordingly.
|
||||
*/
|
||||
mru->lru_grp = (mru->lru_grp + 1) % mru->grp_count;
|
||||
mru->time_zero += mru->grp_time;
|
||||
|
||||
/*
|
||||
* If reaping is so far behind that all the elements on all the
|
||||
* lists have been migrated to the reap list, it's now empty.
|
||||
*/
|
||||
if (++migrated == mru->grp_count) {
|
||||
mru->lru_grp = 0;
|
||||
mru->time_zero = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the first non-empty list from the LRU end. */
|
||||
for (grp = 0; grp < mru->grp_count; grp++) {
|
||||
|
||||
/* Check the grp'th list from the LRU end. */
|
||||
lru_list = mru->lists + ((mru->lru_grp + grp) % mru->grp_count);
|
||||
if (!list_empty(lru_list))
|
||||
return mru->time_zero +
|
||||
(mru->grp_count + grp) * mru->grp_time;
|
||||
}
|
||||
|
||||
/* All the lists must be empty. */
|
||||
mru->lru_grp = 0;
|
||||
mru->time_zero = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When inserting or doing a lookup, an element needs to be inserted into the
|
||||
* MRU list. The lists must be migrated first to ensure that they're
|
||||
* up-to-date, otherwise the new element could be given a shorter lifetime in
|
||||
* the cache than it should.
|
||||
*/
|
||||
STATIC void
|
||||
_xfs_mru_cache_list_insert(
|
||||
xfs_mru_cache_t *mru,
|
||||
xfs_mru_cache_elem_t *elem)
|
||||
{
|
||||
unsigned int grp = 0;
|
||||
unsigned long now = jiffies;
|
||||
|
||||
/*
|
||||
* If the data store is empty, initialise time zero, leave grp set to
|
||||
* zero and start the work queue timer if necessary. Otherwise, set grp
|
||||
* to the number of group times that have elapsed since time zero.
|
||||
*/
|
||||
if (!_xfs_mru_cache_migrate(mru, now)) {
|
||||
mru->time_zero = now;
|
||||
if (!mru->next_reap)
|
||||
mru->next_reap = mru->grp_count * mru->grp_time;
|
||||
} else {
|
||||
grp = (now - mru->time_zero) / mru->grp_time;
|
||||
grp = (mru->lru_grp + grp) % mru->grp_count;
|
||||
}
|
||||
|
||||
/* Insert the element at the tail of the corresponding list. */
|
||||
list_add_tail(&elem->list_node, mru->lists + grp);
|
||||
}
|
||||
|
||||
/*
|
||||
* When destroying or reaping, all the elements that were migrated to the reap
|
||||
* list need to be deleted. For each element this involves removing it from the
|
||||
* data store, removing it from the reap list, calling the client's free
|
||||
* function and deleting the element from the element zone.
|
||||
*/
|
||||
STATIC void
|
||||
_xfs_mru_cache_clear_reap_list(
|
||||
xfs_mru_cache_t *mru)
|
||||
{
|
||||
xfs_mru_cache_elem_t *elem, *next;
|
||||
struct list_head tmp;
|
||||
|
||||
INIT_LIST_HEAD(&tmp);
|
||||
list_for_each_entry_safe(elem, next, &mru->reap_list, list_node) {
|
||||
|
||||
/* Remove the element from the data store. */
|
||||
radix_tree_delete(&mru->store, elem->key);
|
||||
|
||||
/*
|
||||
* remove to temp list so it can be freed without
|
||||
* needing to hold the lock
|
||||
*/
|
||||
list_move(&elem->list_node, &tmp);
|
||||
}
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
|
||||
list_for_each_entry_safe(elem, next, &tmp, list_node) {
|
||||
|
||||
/* Remove the element from the reap list. */
|
||||
list_del_init(&elem->list_node);
|
||||
|
||||
/* Call the client's free function with the key and value pointer. */
|
||||
mru->free_func(elem->key, elem->value);
|
||||
|
||||
/* Free the element structure. */
|
||||
kmem_zone_free(xfs_mru_elem_zone, elem);
|
||||
}
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* We fire the reap timer every group expiry interval so
|
||||
* we always have a reaper ready to run. This makes shutdown
|
||||
* and flushing of the reaper easy to do. Hence we need to
|
||||
* keep when the next reap must occur so we can determine
|
||||
* at each interval whether there is anything we need to do.
|
||||
*/
|
||||
STATIC void
|
||||
_xfs_mru_cache_reap(
|
||||
struct work_struct *work)
|
||||
{
|
||||
xfs_mru_cache_t *mru = container_of(work, xfs_mru_cache_t, work.work);
|
||||
unsigned long now;
|
||||
|
||||
ASSERT(mru && mru->lists);
|
||||
if (!mru || !mru->lists)
|
||||
return;
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
now = jiffies;
|
||||
if (mru->reap_all ||
|
||||
(mru->next_reap && time_after(now, mru->next_reap))) {
|
||||
if (mru->reap_all)
|
||||
now += mru->grp_count * mru->grp_time * 2;
|
||||
mru->next_reap = _xfs_mru_cache_migrate(mru, now);
|
||||
_xfs_mru_cache_clear_reap_list(mru);
|
||||
}
|
||||
|
||||
/*
|
||||
* the process that triggered the reap_all is responsible
|
||||
* for restating the periodic reap if it is required.
|
||||
*/
|
||||
if (!mru->reap_all)
|
||||
queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
|
||||
mru->reap_all = 0;
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
}
|
||||
|
||||
int
|
||||
xfs_mru_cache_init(void)
|
||||
{
|
||||
xfs_mru_elem_zone = kmem_zone_init(sizeof(xfs_mru_cache_elem_t),
|
||||
"xfs_mru_cache_elem");
|
||||
if (!xfs_mru_elem_zone)
|
||||
return ENOMEM;
|
||||
|
||||
xfs_mru_reap_wq = create_singlethread_workqueue("xfs_mru_cache");
|
||||
if (!xfs_mru_reap_wq) {
|
||||
kmem_zone_destroy(xfs_mru_elem_zone);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
xfs_mru_cache_uninit(void)
|
||||
{
|
||||
destroy_workqueue(xfs_mru_reap_wq);
|
||||
kmem_zone_destroy(xfs_mru_elem_zone);
|
||||
}
|
||||
|
||||
/*
|
||||
* To initialise a struct xfs_mru_cache pointer, call xfs_mru_cache_create()
|
||||
* with the address of the pointer, a lifetime value in milliseconds, a group
|
||||
* count and a free function to use when deleting elements. This function
|
||||
* returns 0 if the initialisation was successful.
|
||||
*/
|
||||
int
|
||||
xfs_mru_cache_create(
|
||||
xfs_mru_cache_t **mrup,
|
||||
unsigned int lifetime_ms,
|
||||
unsigned int grp_count,
|
||||
xfs_mru_cache_free_func_t free_func)
|
||||
{
|
||||
xfs_mru_cache_t *mru = NULL;
|
||||
int err = 0, grp;
|
||||
unsigned int grp_time;
|
||||
|
||||
if (mrup)
|
||||
*mrup = NULL;
|
||||
|
||||
if (!mrup || !grp_count || !lifetime_ms || !free_func)
|
||||
return EINVAL;
|
||||
|
||||
if (!(grp_time = msecs_to_jiffies(lifetime_ms) / grp_count))
|
||||
return EINVAL;
|
||||
|
||||
if (!(mru = kmem_zalloc(sizeof(*mru), KM_SLEEP)))
|
||||
return ENOMEM;
|
||||
|
||||
/* An extra list is needed to avoid reaping up to a grp_time early. */
|
||||
mru->grp_count = grp_count + 1;
|
||||
mru->lists = kmem_alloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP);
|
||||
|
||||
if (!mru->lists) {
|
||||
err = ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (grp = 0; grp < mru->grp_count; grp++)
|
||||
INIT_LIST_HEAD(mru->lists + grp);
|
||||
|
||||
/*
|
||||
* We use GFP_KERNEL radix tree preload and do inserts under a
|
||||
* spinlock so GFP_ATOMIC is appropriate for the radix tree itself.
|
||||
*/
|
||||
INIT_RADIX_TREE(&mru->store, GFP_ATOMIC);
|
||||
INIT_LIST_HEAD(&mru->reap_list);
|
||||
spinlock_init(&mru->lock, "xfs_mru_cache");
|
||||
INIT_DELAYED_WORK(&mru->work, _xfs_mru_cache_reap);
|
||||
|
||||
mru->grp_time = grp_time;
|
||||
mru->free_func = free_func;
|
||||
|
||||
/* start up the reaper event */
|
||||
mru->next_reap = 0;
|
||||
mru->reap_all = 0;
|
||||
queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
|
||||
|
||||
*mrup = mru;
|
||||
|
||||
exit:
|
||||
if (err && mru && mru->lists)
|
||||
kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
|
||||
if (err && mru)
|
||||
kmem_free(mru, sizeof(*mru));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call xfs_mru_cache_flush() to flush out all cached entries, calling their
|
||||
* free functions as they're deleted. When this function returns, the caller is
|
||||
* guaranteed that all the free functions for all the elements have finished
|
||||
* executing.
|
||||
*
|
||||
* While we are flushing, we stop the periodic reaper event from triggering.
|
||||
* Normally, we want to restart this periodic event, but if we are shutting
|
||||
* down the cache we do not want it restarted. hence the restart parameter
|
||||
* where 0 = do not restart reaper and 1 = restart reaper.
|
||||
*/
|
||||
void
|
||||
xfs_mru_cache_flush(
|
||||
xfs_mru_cache_t *mru,
|
||||
int restart)
|
||||
{
|
||||
if (!mru || !mru->lists)
|
||||
return;
|
||||
|
||||
cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
mru->reap_all = 1;
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
|
||||
queue_work(xfs_mru_reap_wq, &mru->work.work);
|
||||
flush_workqueue(xfs_mru_reap_wq);
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
WARN_ON_ONCE(mru->reap_all != 0);
|
||||
mru->reap_all = 0;
|
||||
if (restart)
|
||||
queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
}
|
||||
|
||||
void
|
||||
xfs_mru_cache_destroy(
|
||||
xfs_mru_cache_t *mru)
|
||||
{
|
||||
if (!mru || !mru->lists)
|
||||
return;
|
||||
|
||||
/* we don't want the reaper to restart here */
|
||||
xfs_mru_cache_flush(mru, 0);
|
||||
|
||||
kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
|
||||
kmem_free(mru, sizeof(*mru));
|
||||
}
|
||||
|
||||
/*
|
||||
* To insert an element, call xfs_mru_cache_insert() with the data store, the
|
||||
* element's key and the client data pointer. This function returns 0 on
|
||||
* success or ENOMEM if memory for the data element couldn't be allocated.
|
||||
*/
|
||||
int
|
||||
xfs_mru_cache_insert(
|
||||
xfs_mru_cache_t *mru,
|
||||
unsigned long key,
|
||||
void *value)
|
||||
{
|
||||
xfs_mru_cache_elem_t *elem;
|
||||
|
||||
ASSERT(mru && mru->lists);
|
||||
if (!mru || !mru->lists)
|
||||
return EINVAL;
|
||||
|
||||
elem = kmem_zone_zalloc(xfs_mru_elem_zone, KM_SLEEP);
|
||||
if (!elem)
|
||||
return ENOMEM;
|
||||
|
||||
if (radix_tree_preload(GFP_KERNEL)) {
|
||||
kmem_zone_free(xfs_mru_elem_zone, elem);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&elem->list_node);
|
||||
elem->key = key;
|
||||
elem->value = value;
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
|
||||
radix_tree_insert(&mru->store, key, elem);
|
||||
radix_tree_preload_end();
|
||||
_xfs_mru_cache_list_insert(mru, elem);
|
||||
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* To remove an element without calling the free function, call
|
||||
* xfs_mru_cache_remove() with the data store and the element's key. On success
|
||||
* the client data pointer for the removed element is returned, otherwise this
|
||||
* function will return a NULL pointer.
|
||||
*/
|
||||
void *
|
||||
xfs_mru_cache_remove(
|
||||
xfs_mru_cache_t *mru,
|
||||
unsigned long key)
|
||||
{
|
||||
xfs_mru_cache_elem_t *elem;
|
||||
void *value = NULL;
|
||||
|
||||
ASSERT(mru && mru->lists);
|
||||
if (!mru || !mru->lists)
|
||||
return NULL;
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
elem = radix_tree_delete(&mru->store, key);
|
||||
if (elem) {
|
||||
value = elem->value;
|
||||
list_del(&elem->list_node);
|
||||
}
|
||||
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
|
||||
if (elem)
|
||||
kmem_zone_free(xfs_mru_elem_zone, elem);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* To remove and element and call the free function, call xfs_mru_cache_delete()
|
||||
* with the data store and the element's key.
|
||||
*/
|
||||
void
|
||||
xfs_mru_cache_delete(
|
||||
xfs_mru_cache_t *mru,
|
||||
unsigned long key)
|
||||
{
|
||||
void *value = xfs_mru_cache_remove(mru, key);
|
||||
|
||||
if (value)
|
||||
mru->free_func(key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* To look up an element using its key, call xfs_mru_cache_lookup() with the
|
||||
* data store and the element's key. If found, the element will be moved to the
|
||||
* head of the MRU list to indicate that it's been touched.
|
||||
*
|
||||
* The internal data structures are protected by a spinlock that is STILL HELD
|
||||
* when this function returns. Call xfs_mru_cache_done() to release it. Note
|
||||
* that it is not safe to call any function that might sleep in the interim.
|
||||
*
|
||||
* The implementation could have used reference counting to avoid this
|
||||
* restriction, but since most clients simply want to get, set or test a member
|
||||
* of the returned data structure, the extra per-element memory isn't warranted.
|
||||
*
|
||||
* If the element isn't found, this function returns NULL and the spinlock is
|
||||
* released. xfs_mru_cache_done() should NOT be called when this occurs.
|
||||
*/
|
||||
void *
|
||||
xfs_mru_cache_lookup(
|
||||
xfs_mru_cache_t *mru,
|
||||
unsigned long key)
|
||||
{
|
||||
xfs_mru_cache_elem_t *elem;
|
||||
|
||||
ASSERT(mru && mru->lists);
|
||||
if (!mru || !mru->lists)
|
||||
return NULL;
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
elem = radix_tree_lookup(&mru->store, key);
|
||||
if (elem) {
|
||||
list_del(&elem->list_node);
|
||||
_xfs_mru_cache_list_insert(mru, elem);
|
||||
}
|
||||
else
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
|
||||
return elem ? elem->value : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* To look up an element using its key, but leave its location in the internal
|
||||
* lists alone, call xfs_mru_cache_peek(). If the element isn't found, this
|
||||
* function returns NULL.
|
||||
*
|
||||
* See the comments above the declaration of the xfs_mru_cache_lookup() function
|
||||
* for important locking information pertaining to this call.
|
||||
*/
|
||||
void *
|
||||
xfs_mru_cache_peek(
|
||||
xfs_mru_cache_t *mru,
|
||||
unsigned long key)
|
||||
{
|
||||
xfs_mru_cache_elem_t *elem;
|
||||
|
||||
ASSERT(mru && mru->lists);
|
||||
if (!mru || !mru->lists)
|
||||
return NULL;
|
||||
|
||||
mutex_spinlock(&mru->lock);
|
||||
elem = radix_tree_lookup(&mru->store, key);
|
||||
if (!elem)
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
|
||||
return elem ? elem->value : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* To release the internal data structure spinlock after having performed an
|
||||
* xfs_mru_cache_lookup() or an xfs_mru_cache_peek(), call xfs_mru_cache_done()
|
||||
* with the data store pointer.
|
||||
*/
|
||||
void
|
||||
xfs_mru_cache_done(
|
||||
xfs_mru_cache_t *mru)
|
||||
{
|
||||
mutex_spinunlock(&mru->lock, 0);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __XFS_MRU_CACHE_H__
|
||||
#define __XFS_MRU_CACHE_H__
|
||||
|
||||
|
||||
/* Function pointer type for callback to free a client's data pointer. */
|
||||
typedef void (*xfs_mru_cache_free_func_t)(unsigned long, void*);
|
||||
|
||||
typedef struct xfs_mru_cache
|
||||
{
|
||||
struct radix_tree_root store; /* Core storage data structure. */
|
||||
struct list_head *lists; /* Array of lists, one per grp. */
|
||||
struct list_head reap_list; /* Elements overdue for reaping. */
|
||||
spinlock_t lock; /* Lock to protect this struct. */
|
||||
unsigned int grp_count; /* Number of discrete groups. */
|
||||
unsigned int grp_time; /* Time period spanned by grps. */
|
||||
unsigned int lru_grp; /* Group containing time zero. */
|
||||
unsigned long time_zero; /* Time first element was added. */
|
||||
unsigned long next_reap; /* Time that the reaper should
|
||||
next do something. */
|
||||
unsigned int reap_all; /* if set, reap all lists */
|
||||
xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */
|
||||
struct delayed_work work; /* Workqueue data for reaping. */
|
||||
} xfs_mru_cache_t;
|
||||
|
||||
int xfs_mru_cache_init(void);
|
||||
void xfs_mru_cache_uninit(void);
|
||||
int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms,
|
||||
unsigned int grp_count,
|
||||
xfs_mru_cache_free_func_t free_func);
|
||||
void xfs_mru_cache_flush(xfs_mru_cache_t *mru, int restart);
|
||||
void xfs_mru_cache_destroy(struct xfs_mru_cache *mru);
|
||||
int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key,
|
||||
void *value);
|
||||
void * xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key);
|
||||
void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key);
|
||||
void *xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key);
|
||||
void *xfs_mru_cache_peek(struct xfs_mru_cache *mru, unsigned long key);
|
||||
void xfs_mru_cache_done(struct xfs_mru_cache *mru);
|
||||
|
||||
#endif /* __XFS_MRU_CACHE_H__ */
|
|
@ -1882,11 +1882,13 @@ xfs_growfs_rt(
|
|||
(nrblocks = in->newblocks) <= sbp->sb_rblocks ||
|
||||
(sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
|
||||
return XFS_ERROR(EINVAL);
|
||||
if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
|
||||
return error;
|
||||
/*
|
||||
* Read in the last block of the device, make sure it exists.
|
||||
*/
|
||||
error = xfs_read_buf(mp, mp->m_rtdev_targp,
|
||||
XFS_FSB_TO_BB(mp, in->newblocks - 1),
|
||||
XFS_FSB_TO_BB(mp, nrblocks - 1),
|
||||
XFS_FSB_TO_BB(mp, 1), 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
|
|
@ -71,6 +71,34 @@ xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb)
|
|||
XFS_FSB_TO_DADDR((io)->io_mount, (fsb)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Flags for xfs_free_eofblocks
|
||||
*/
|
||||
#define XFS_FREE_EOF_LOCK (1<<0)
|
||||
#define XFS_FREE_EOF_NOLOCK (1<<1)
|
||||
|
||||
|
||||
/*
|
||||
* helper function to extract extent size hint from inode
|
||||
*/
|
||||
STATIC_INLINE xfs_extlen_t
|
||||
xfs_get_extsz_hint(
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
xfs_extlen_t extsz;
|
||||
|
||||
if (unlikely(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
|
||||
extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
|
||||
? ip->i_d.di_extsize
|
||||
: ip->i_mount->m_sb.sb_rextsize;
|
||||
ASSERT(extsz);
|
||||
} else {
|
||||
extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
|
||||
? ip->i_d.di_extsize : 0;
|
||||
}
|
||||
return extsz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototypes for functions in xfs_rw.c.
|
||||
*/
|
||||
|
@ -91,10 +119,12 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp,
|
|||
extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
|
||||
extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
|
||||
extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
|
||||
cred_t *credp);
|
||||
cred_t *credp);
|
||||
extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
|
||||
xfs_off_t offset, cred_t *credp, int flags);
|
||||
xfs_off_t offset, cred_t *credp, int flags);
|
||||
extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
|
||||
cred_t *credp);
|
||||
cred_t *credp);
|
||||
extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip,
|
||||
int flags);
|
||||
|
||||
#endif /* __XFS_RW_H__ */
|
||||
|
|
|
@ -74,12 +74,13 @@ struct xfs_mount;
|
|||
*/
|
||||
#define XFS_SB_VERSION2_REALFBITS 0x00ffffff /* Mask: features */
|
||||
#define XFS_SB_VERSION2_RESERVED1BIT 0x00000001
|
||||
#define XFS_SB_VERSION2_RESERVED2BIT 0x00000002
|
||||
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */
|
||||
#define XFS_SB_VERSION2_RESERVED4BIT 0x00000004
|
||||
#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
|
||||
|
||||
#define XFS_SB_VERSION2_OKREALFBITS \
|
||||
(XFS_SB_VERSION2_ATTR2BIT)
|
||||
(XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
|
||||
XFS_SB_VERSION2_ATTR2BIT)
|
||||
#define XFS_SB_VERSION2_OKSASHFBITS \
|
||||
(0)
|
||||
#define XFS_SB_VERSION2_OKREALBITS \
|
||||
|
@ -181,6 +182,9 @@ typedef enum {
|
|||
#define XFS_SB_SHARED_VN XFS_SB_MVAL(SHARED_VN)
|
||||
#define XFS_SB_UNIT XFS_SB_MVAL(UNIT)
|
||||
#define XFS_SB_WIDTH XFS_SB_MVAL(WIDTH)
|
||||
#define XFS_SB_ICOUNT XFS_SB_MVAL(ICOUNT)
|
||||
#define XFS_SB_IFREE XFS_SB_MVAL(IFREE)
|
||||
#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)
|
||||
#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)
|
||||
#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)
|
||||
#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1)
|
||||
|
@ -188,7 +192,7 @@ typedef enum {
|
|||
(XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
|
||||
XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
|
||||
XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
|
||||
XFS_SB_FEATURES2)
|
||||
XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2)
|
||||
|
||||
|
||||
/*
|
||||
|
@ -414,6 +418,12 @@ static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
|
|||
* ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT)
|
||||
*/
|
||||
|
||||
static inline int xfs_sb_version_haslazysbcount(xfs_sb_t *sbp)
|
||||
{
|
||||
return (XFS_SB_VERSION_HASMOREBITS(sbp) && \
|
||||
((sbp)->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT));
|
||||
}
|
||||
|
||||
#define XFS_SB_VERSION_HASATTR2(sbp) xfs_sb_version_hasattr2(sbp)
|
||||
static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp)
|
||||
{
|
||||
|
|
|
@ -427,6 +427,14 @@ undo_blocks:
|
|||
*
|
||||
* Mark the transaction structure to indicate that the superblock
|
||||
* needs to be updated before committing.
|
||||
*
|
||||
* Because we may not be keeping track of allocated/free inodes and
|
||||
* used filesystem blocks in the superblock, we do not mark the
|
||||
* superblock dirty in this transaction if we modify these fields.
|
||||
* We still need to update the transaction deltas so that they get
|
||||
* applied to the incore superblock, but we don't want them to
|
||||
* cause the superblock to get locked and logged if these are the
|
||||
* only fields in the superblock that the transaction modifies.
|
||||
*/
|
||||
void
|
||||
xfs_trans_mod_sb(
|
||||
|
@ -434,13 +442,19 @@ xfs_trans_mod_sb(
|
|||
uint field,
|
||||
int64_t delta)
|
||||
{
|
||||
uint32_t flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY);
|
||||
xfs_mount_t *mp = tp->t_mountp;
|
||||
|
||||
switch (field) {
|
||||
case XFS_TRANS_SB_ICOUNT:
|
||||
tp->t_icount_delta += delta;
|
||||
if (xfs_sb_version_haslazysbcount(&mp->m_sb))
|
||||
flags &= ~XFS_TRANS_SB_DIRTY;
|
||||
break;
|
||||
case XFS_TRANS_SB_IFREE:
|
||||
tp->t_ifree_delta += delta;
|
||||
if (xfs_sb_version_haslazysbcount(&mp->m_sb))
|
||||
flags &= ~XFS_TRANS_SB_DIRTY;
|
||||
break;
|
||||
case XFS_TRANS_SB_FDBLOCKS:
|
||||
/*
|
||||
|
@ -453,6 +467,8 @@ xfs_trans_mod_sb(
|
|||
ASSERT(tp->t_blk_res_used <= tp->t_blk_res);
|
||||
}
|
||||
tp->t_fdblocks_delta += delta;
|
||||
if (xfs_sb_version_haslazysbcount(&mp->m_sb))
|
||||
flags &= ~XFS_TRANS_SB_DIRTY;
|
||||
break;
|
||||
case XFS_TRANS_SB_RES_FDBLOCKS:
|
||||
/*
|
||||
|
@ -462,6 +478,8 @@ xfs_trans_mod_sb(
|
|||
*/
|
||||
ASSERT(delta < 0);
|
||||
tp->t_res_fdblocks_delta += delta;
|
||||
if (xfs_sb_version_haslazysbcount(&mp->m_sb))
|
||||
flags &= ~XFS_TRANS_SB_DIRTY;
|
||||
break;
|
||||
case XFS_TRANS_SB_FREXTENTS:
|
||||
/*
|
||||
|
@ -515,7 +533,7 @@ xfs_trans_mod_sb(
|
|||
return;
|
||||
}
|
||||
|
||||
tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY);
|
||||
tp->t_flags |= flags;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -544,18 +562,23 @@ xfs_trans_apply_sb_deltas(
|
|||
(tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
|
||||
tp->t_ag_btree_delta));
|
||||
|
||||
if (tp->t_icount_delta != 0) {
|
||||
INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
|
||||
}
|
||||
if (tp->t_ifree_delta != 0) {
|
||||
INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
|
||||
}
|
||||
/*
|
||||
* Only update the superblock counters if we are logging them
|
||||
*/
|
||||
if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
|
||||
if (tp->t_icount_delta != 0) {
|
||||
INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
|
||||
}
|
||||
if (tp->t_ifree_delta != 0) {
|
||||
INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
|
||||
}
|
||||
|
||||
if (tp->t_fdblocks_delta != 0) {
|
||||
INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
|
||||
}
|
||||
if (tp->t_res_fdblocks_delta != 0) {
|
||||
INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
|
||||
if (tp->t_fdblocks_delta != 0) {
|
||||
INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
|
||||
}
|
||||
if (tp->t_res_fdblocks_delta != 0) {
|
||||
INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
|
||||
}
|
||||
}
|
||||
|
||||
if (tp->t_frextents_delta != 0) {
|
||||
|
@ -615,11 +638,23 @@ xfs_trans_apply_sb_deltas(
|
|||
}
|
||||
|
||||
/*
|
||||
* xfs_trans_unreserve_and_mod_sb() is called to release unused
|
||||
* reservations and apply superblock counter changes to the in-core
|
||||
* superblock.
|
||||
* xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
|
||||
* and apply superblock counter changes to the in-core superblock. The
|
||||
* t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT
|
||||
* applied to the in-core superblock. The idea is that that has already been
|
||||
* done.
|
||||
*
|
||||
* This is done efficiently with a single call to xfs_mod_incore_sb_batch().
|
||||
* However, we have to ensure that we only modify each superblock field only
|
||||
* once because the application of the delta values may not be atomic. That can
|
||||
* lead to ENOSPC races occurring if we have two separate modifcations of the
|
||||
* free space counter to put back the entire reservation and then take away
|
||||
* what we used.
|
||||
*
|
||||
* If we are not logging superblock counters, then the inode allocated/free and
|
||||
* used block counts are not updated in the on disk superblock. In this case,
|
||||
* XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
|
||||
* still need to update the incore superblock with the changes.
|
||||
*/
|
||||
STATIC void
|
||||
xfs_trans_unreserve_and_mod_sb(
|
||||
|
@ -627,40 +662,49 @@ xfs_trans_unreserve_and_mod_sb(
|
|||
{
|
||||
xfs_mod_sb_t msb[14]; /* If you add cases, add entries */
|
||||
xfs_mod_sb_t *msbp;
|
||||
xfs_mount_t *mp = tp->t_mountp;
|
||||
/* REFERENCED */
|
||||
int error;
|
||||
int rsvd;
|
||||
int64_t blkdelta = 0;
|
||||
int64_t rtxdelta = 0;
|
||||
|
||||
msbp = msb;
|
||||
rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
|
||||
|
||||
/*
|
||||
* Release any reserved blocks. Any that were allocated
|
||||
* will be taken back again by fdblocks_delta below.
|
||||
*/
|
||||
if (tp->t_blk_res > 0) {
|
||||
/* calculate free blocks delta */
|
||||
if (tp->t_blk_res > 0)
|
||||
blkdelta = tp->t_blk_res;
|
||||
|
||||
if ((tp->t_fdblocks_delta != 0) &&
|
||||
(xfs_sb_version_haslazysbcount(&mp->m_sb) ||
|
||||
(tp->t_flags & XFS_TRANS_SB_DIRTY)))
|
||||
blkdelta += tp->t_fdblocks_delta;
|
||||
|
||||
if (blkdelta != 0) {
|
||||
msbp->msb_field = XFS_SBS_FDBLOCKS;
|
||||
msbp->msb_delta = tp->t_blk_res;
|
||||
msbp->msb_delta = blkdelta;
|
||||
msbp++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release any reserved real time extents . Any that were
|
||||
* allocated will be taken back again by frextents_delta below.
|
||||
*/
|
||||
if (tp->t_rtx_res > 0) {
|
||||
/* calculate free realtime extents delta */
|
||||
if (tp->t_rtx_res > 0)
|
||||
rtxdelta = tp->t_rtx_res;
|
||||
|
||||
if ((tp->t_frextents_delta != 0) &&
|
||||
(tp->t_flags & XFS_TRANS_SB_DIRTY))
|
||||
rtxdelta += tp->t_frextents_delta;
|
||||
|
||||
if (rtxdelta != 0) {
|
||||
msbp->msb_field = XFS_SBS_FREXTENTS;
|
||||
msbp->msb_delta = tp->t_rtx_res;
|
||||
msbp->msb_delta = rtxdelta;
|
||||
msbp++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply any superblock modifications to the in-core version.
|
||||
* The t_res_fdblocks_delta and t_res_frextents_delta fields are
|
||||
* explicitly NOT applied to the in-core superblock.
|
||||
* The idea is that that has already been done.
|
||||
*/
|
||||
if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
|
||||
/* apply remaining deltas */
|
||||
|
||||
if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
|
||||
(tp->t_flags & XFS_TRANS_SB_DIRTY)) {
|
||||
if (tp->t_icount_delta != 0) {
|
||||
msbp->msb_field = XFS_SBS_ICOUNT;
|
||||
msbp->msb_delta = tp->t_icount_delta;
|
||||
|
@ -671,16 +715,9 @@ xfs_trans_unreserve_and_mod_sb(
|
|||
msbp->msb_delta = tp->t_ifree_delta;
|
||||
msbp++;
|
||||
}
|
||||
if (tp->t_fdblocks_delta != 0) {
|
||||
msbp->msb_field = XFS_SBS_FDBLOCKS;
|
||||
msbp->msb_delta = tp->t_fdblocks_delta;
|
||||
msbp++;
|
||||
}
|
||||
if (tp->t_frextents_delta != 0) {
|
||||
msbp->msb_field = XFS_SBS_FREXTENTS;
|
||||
msbp->msb_delta = tp->t_frextents_delta;
|
||||
msbp++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
|
||||
if (tp->t_dblocks_delta != 0) {
|
||||
msbp->msb_field = XFS_SBS_DBLOCKS;
|
||||
msbp->msb_delta = tp->t_dblocks_delta;
|
||||
|
|
|
@ -94,7 +94,8 @@ typedef struct xfs_trans_header {
|
|||
#define XFS_TRANS_GROWFSRT_ZERO 38
|
||||
#define XFS_TRANS_GROWFSRT_FREE 39
|
||||
#define XFS_TRANS_SWAPEXT 40
|
||||
#define XFS_TRANS_TYPE_MAX 40
|
||||
#define XFS_TRANS_SB_COUNT 41
|
||||
#define XFS_TRANS_TYPE_MAX 41
|
||||
/* new transaction types need to be reflected in xfs_logprint(8) */
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
#include "xfs_acl.h"
|
||||
#include "xfs_attr.h"
|
||||
#include "xfs_clnt.h"
|
||||
#include "xfs_mru_cache.h"
|
||||
#include "xfs_filestream.h"
|
||||
#include "xfs_fsops.h"
|
||||
|
||||
STATIC int xfs_sync(bhv_desc_t *, int, cred_t *);
|
||||
|
@ -81,6 +83,8 @@ xfs_init(void)
|
|||
xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
|
||||
xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
|
||||
xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
|
||||
xfs_mru_cache_init();
|
||||
xfs_filestream_init();
|
||||
|
||||
/*
|
||||
* The size of the zone allocated buf log item is the maximum
|
||||
|
@ -164,6 +168,8 @@ xfs_cleanup(void)
|
|||
xfs_cleanup_procfs();
|
||||
xfs_sysctl_unregister();
|
||||
xfs_refcache_destroy();
|
||||
xfs_filestream_uninit();
|
||||
xfs_mru_cache_uninit();
|
||||
xfs_acl_zone_destroy(xfs_acl_zone);
|
||||
|
||||
#ifdef XFS_DIR2_TRACE
|
||||
|
@ -320,6 +326,9 @@ xfs_start_flags(
|
|||
else
|
||||
mp->m_flags &= ~XFS_MOUNT_BARRIER;
|
||||
|
||||
if (ap->flags2 & XFSMNT2_FILESTREAMS)
|
||||
mp->m_flags |= XFS_MOUNT_FILESTREAMS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -518,6 +527,9 @@ xfs_mount(
|
|||
if (mp->m_flags & XFS_MOUNT_BARRIER)
|
||||
xfs_mountfs_check_barriers(mp);
|
||||
|
||||
if ((error = xfs_filestream_mount(mp)))
|
||||
goto error2;
|
||||
|
||||
error = XFS_IOINIT(vfsp, args, flags);
|
||||
if (error)
|
||||
goto error2;
|
||||
|
@ -575,6 +587,13 @@ xfs_unmount(
|
|||
*/
|
||||
xfs_refcache_purge_mp(mp);
|
||||
|
||||
/*
|
||||
* Blow away any referenced inode in the filestreams cache.
|
||||
* This can and will cause log traffic as inodes go inactive
|
||||
* here.
|
||||
*/
|
||||
xfs_filestream_unmount(mp);
|
||||
|
||||
XFS_bflush(mp->m_ddev_targp);
|
||||
error = xfs_unmount_flush(mp, 0);
|
||||
if (error)
|
||||
|
@ -640,7 +659,7 @@ xfs_quiesce_fs(
|
|||
* we can write the unmount record.
|
||||
*/
|
||||
do {
|
||||
xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL);
|
||||
xfs_syncsub(mp, SYNC_INODE_QUIESCE, NULL);
|
||||
pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
|
||||
if (!pincount) {
|
||||
delay(50);
|
||||
|
@ -651,6 +670,30 @@ xfs_quiesce_fs(
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second stage of a quiesce. The data is already synced, now we have to take
|
||||
* care of the metadata. New transactions are already blocked, so we need to
|
||||
* wait for any remaining transactions to drain out before proceding.
|
||||
*/
|
||||
STATIC void
|
||||
xfs_attr_quiesce(
|
||||
xfs_mount_t *mp)
|
||||
{
|
||||
/* wait for all modifications to complete */
|
||||
while (atomic_read(&mp->m_active_trans) > 0)
|
||||
delay(100);
|
||||
|
||||
/* flush inodes and push all remaining buffers out to disk */
|
||||
xfs_quiesce_fs(mp);
|
||||
|
||||
ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
|
||||
|
||||
/* Push the superblock and write an unmount record */
|
||||
xfs_log_sbcount(mp, 1);
|
||||
xfs_log_unmount_write(mp);
|
||||
xfs_unmountfs_writesb(mp);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_mntupdate(
|
||||
bhv_desc_t *bdp,
|
||||
|
@ -670,10 +713,9 @@ xfs_mntupdate(
|
|||
mp->m_flags &= ~XFS_MOUNT_BARRIER;
|
||||
}
|
||||
} else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */
|
||||
bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL);
|
||||
xfs_quiesce_fs(mp);
|
||||
xfs_log_unmount_write(mp);
|
||||
xfs_unmountfs_writesb(mp);
|
||||
xfs_filestream_flush(mp);
|
||||
bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL);
|
||||
xfs_attr_quiesce(mp);
|
||||
vfsp->vfs_flag |= VFS_RDONLY;
|
||||
}
|
||||
return 0;
|
||||
|
@ -887,6 +929,9 @@ xfs_sync(
|
|||
{
|
||||
xfs_mount_t *mp = XFS_BHVTOM(bdp);
|
||||
|
||||
if (flags & SYNC_IOWAIT)
|
||||
xfs_filestream_flush(mp);
|
||||
|
||||
return xfs_syncsub(mp, flags, NULL);
|
||||
}
|
||||
|
||||
|
@ -1128,58 +1173,41 @@ xfs_sync_inodes(
|
|||
* in the inode list.
|
||||
*/
|
||||
|
||||
if ((flags & SYNC_CLOSE) && (vp != NULL)) {
|
||||
/*
|
||||
* This is the shutdown case. We just need to
|
||||
* flush and invalidate all the pages associated
|
||||
* with the inode. Drop the inode lock since
|
||||
* we can't hold it across calls to the buffer
|
||||
* cache.
|
||||
*
|
||||
* We don't set the VREMAPPING bit in the vnode
|
||||
* here, because we don't hold the vnode lock
|
||||
* exclusively. It doesn't really matter, though,
|
||||
* because we only come here when we're shutting
|
||||
* down anyway.
|
||||
*/
|
||||
/*
|
||||
* If we have to flush data or wait for I/O completion
|
||||
* we need to drop the ilock that we currently hold.
|
||||
* If we need to drop the lock, insert a marker if we
|
||||
* have not already done so.
|
||||
*/
|
||||
if ((flags & (SYNC_CLOSE|SYNC_IOWAIT)) ||
|
||||
((flags & SYNC_DELWRI) && VN_DIRTY(vp))) {
|
||||
if (mount_locked) {
|
||||
IPOINTER_INSERT(ip, mp);
|
||||
}
|
||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||
|
||||
if (XFS_FORCED_SHUTDOWN(mp)) {
|
||||
bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
|
||||
} else {
|
||||
error = bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF);
|
||||
}
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||
|
||||
} else if ((flags & SYNC_DELWRI) && (vp != NULL)) {
|
||||
if (VN_DIRTY(vp)) {
|
||||
/* We need to have dropped the lock here,
|
||||
* so insert a marker if we have not already
|
||||
* done so.
|
||||
*/
|
||||
if (mount_locked) {
|
||||
IPOINTER_INSERT(ip, mp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the inode lock since we can't hold it
|
||||
* across calls to the buffer cache.
|
||||
*/
|
||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||
if (flags & SYNC_CLOSE) {
|
||||
/* Shutdown case. Flush and invalidate. */
|
||||
if (XFS_FORCED_SHUTDOWN(mp))
|
||||
bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
|
||||
else
|
||||
error = bhv_vop_flushinval_pages(vp, 0,
|
||||
-1, FI_REMAPF);
|
||||
} else if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) {
|
||||
error = bhv_vop_flush_pages(vp, (xfs_off_t)0,
|
||||
-1, fflag, FI_NONE);
|
||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||
}
|
||||
|
||||
/*
|
||||
* When freezing, we need to wait ensure all I/O (including direct
|
||||
* I/O) is complete to ensure no further data modification can take
|
||||
* place after this point
|
||||
*/
|
||||
if (flags & SYNC_IOWAIT)
|
||||
vn_iowait(vp);
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||
}
|
||||
/*
|
||||
* When freezing, we need to wait ensure all I/O (including direct
|
||||
* I/O) is complete to ensure no further data modification can take
|
||||
* place after this point
|
||||
*/
|
||||
if (flags & SYNC_IOWAIT)
|
||||
vn_iowait(vp);
|
||||
|
||||
if (flags & SYNC_BDFLUSH) {
|
||||
if ((flags & SYNC_ATTR) &&
|
||||
|
@ -1513,6 +1541,15 @@ xfs_syncsub(
|
|||
xfs_refcache_purge_some(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
* If asked, update the disk superblock with incore counter values if we
|
||||
* are using non-persistent counters so that they don't get too far out
|
||||
* of sync if we crash or get a forced shutdown. We don't want to force
|
||||
* this to disk, just get a transaction into the iclogs....
|
||||
*/
|
||||
if (flags & SYNC_SUPER)
|
||||
xfs_log_sbcount(mp, 0);
|
||||
|
||||
/*
|
||||
* Now check to see if the log needs a "dummy" transaction.
|
||||
*/
|
||||
|
@ -1645,6 +1682,7 @@ xfs_vget(
|
|||
* in stat(). */
|
||||
#define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */
|
||||
#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */
|
||||
#define MNTOPT_FILESTREAM "filestreams" /* use filestreams allocator */
|
||||
|
||||
STATIC unsigned long
|
||||
suffix_strtoul(char *s, char **endp, unsigned int base)
|
||||
|
@ -1831,6 +1869,8 @@ xfs_parseargs(
|
|||
args->flags |= XFSMNT_ATTR2;
|
||||
} else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
|
||||
args->flags &= ~XFSMNT_ATTR2;
|
||||
} else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
|
||||
args->flags2 |= XFSMNT2_FILESTREAMS;
|
||||
} else if (!strcmp(this_char, "osyncisdsync")) {
|
||||
/* no-op, this is now the default */
|
||||
cmn_err(CE_WARN,
|
||||
|
@ -1959,9 +1999,9 @@ xfs_showargs(
|
|||
}
|
||||
|
||||
/*
|
||||
* Second stage of a freeze. The data is already frozen, now we have to take
|
||||
* care of the metadata. New transactions are already blocked, so we need to
|
||||
* wait for any remaining transactions to drain out before proceding.
|
||||
* Second stage of a freeze. The data is already frozen so we only
|
||||
* need to take care of themetadata. Once that's done write a dummy
|
||||
* record to dirty the log in case of a crash while frozen.
|
||||
*/
|
||||
STATIC void
|
||||
xfs_freeze(
|
||||
|
@ -1969,18 +2009,7 @@ xfs_freeze(
|
|||
{
|
||||
xfs_mount_t *mp = XFS_BHVTOM(bdp);
|
||||
|
||||
/* wait for all modifications to complete */
|
||||
while (atomic_read(&mp->m_active_trans) > 0)
|
||||
delay(100);
|
||||
|
||||
/* flush inodes and push all remaining buffers out to disk */
|
||||
xfs_quiesce_fs(mp);
|
||||
|
||||
ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
|
||||
|
||||
/* Push the superblock and write an unmount record */
|
||||
xfs_log_unmount_write(mp);
|
||||
xfs_unmountfs_writesb(mp);
|
||||
xfs_attr_quiesce(mp);
|
||||
xfs_fs_log_dummy(mp);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "xfs_refcache.h"
|
||||
#include "xfs_trans_space.h"
|
||||
#include "xfs_log_priv.h"
|
||||
#include "xfs_filestream.h"
|
||||
|
||||
STATIC int
|
||||
xfs_open(
|
||||
|
@ -77,36 +78,6 @@ xfs_open(
|
|||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_close(
|
||||
bhv_desc_t *bdp,
|
||||
int flags,
|
||||
lastclose_t lastclose,
|
||||
cred_t *credp)
|
||||
{
|
||||
bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
|
||||
xfs_inode_t *ip = XFS_BHVTOI(bdp);
|
||||
|
||||
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
|
||||
return XFS_ERROR(EIO);
|
||||
|
||||
if (lastclose != L_TRUE || !VN_ISREG(vp))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we previously truncated this file and removed old data in
|
||||
* the process, we want to initiate "early" writeout on the last
|
||||
* close. This is an attempt to combat the notorious NULL files
|
||||
* problem which is particularly noticable from a truncate down,
|
||||
* buffered (re-)write (delalloc), followed by a crash. What we
|
||||
* are effectively doing here is significantly reducing the time
|
||||
* window where we'd otherwise be exposed to that problem.
|
||||
*/
|
||||
if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
|
||||
return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_getattr
|
||||
*/
|
||||
|
@ -183,9 +154,8 @@ xfs_getattr(
|
|||
* realtime extent size or the realtime volume's
|
||||
* extent size.
|
||||
*/
|
||||
vap->va_blocksize = ip->i_d.di_extsize ?
|
||||
(ip->i_d.di_extsize << mp->m_sb.sb_blocklog) :
|
||||
(mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog);
|
||||
vap->va_blocksize =
|
||||
xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -814,6 +784,8 @@ xfs_setattr(
|
|||
di_flags |= XFS_DIFLAG_PROJINHERIT;
|
||||
if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
|
||||
di_flags |= XFS_DIFLAG_NODEFRAG;
|
||||
if (vap->va_xflags & XFS_XFLAG_FILESTREAM)
|
||||
di_flags |= XFS_DIFLAG_FILESTREAM;
|
||||
if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
|
||||
if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
|
||||
di_flags |= XFS_DIFLAG_RTINHERIT;
|
||||
|
@ -1201,13 +1173,15 @@ xfs_fsync(
|
|||
}
|
||||
|
||||
/*
|
||||
* This is called by xfs_inactive to free any blocks beyond eof,
|
||||
* when the link count isn't zero.
|
||||
* This is called by xfs_inactive to free any blocks beyond eof
|
||||
* when the link count isn't zero and by xfs_dm_punch_hole() when
|
||||
* punching a hole to EOF.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_inactive_free_eofblocks(
|
||||
int
|
||||
xfs_free_eofblocks(
|
||||
xfs_mount_t *mp,
|
||||
xfs_inode_t *ip)
|
||||
xfs_inode_t *ip,
|
||||
int flags)
|
||||
{
|
||||
xfs_trans_t *tp;
|
||||
int error;
|
||||
|
@ -1216,6 +1190,7 @@ xfs_inactive_free_eofblocks(
|
|||
xfs_filblks_t map_len;
|
||||
int nimaps;
|
||||
xfs_bmbt_irec_t imap;
|
||||
int use_iolock = (flags & XFS_FREE_EOF_LOCK);
|
||||
|
||||
/*
|
||||
* Figure out if there are any blocks beyond the end
|
||||
|
@ -1256,11 +1231,14 @@ xfs_inactive_free_eofblocks(
|
|||
* cache and we can't
|
||||
* do that within a transaction.
|
||||
*/
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||
if (use_iolock)
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||
error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
|
||||
ip->i_size);
|
||||
if (error) {
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
xfs_trans_cancel(tp, 0);
|
||||
if (use_iolock)
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1297,7 +1275,8 @@ xfs_inactive_free_eofblocks(
|
|||
error = xfs_trans_commit(tp,
|
||||
XFS_TRANS_RELEASE_LOG_RES);
|
||||
}
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
||||
xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)
|
||||
: XFS_ILOCK_EXCL));
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -1560,6 +1539,31 @@ xfs_release(
|
|||
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
|
||||
return 0;
|
||||
|
||||
if (!XFS_FORCED_SHUTDOWN(mp)) {
|
||||
/*
|
||||
* If we are using filestreams, and we have an unlinked
|
||||
* file that we are processing the last close on, then nothing
|
||||
* will be able to reopen and write to this file. Purge this
|
||||
* inode from the filestreams cache so that it doesn't delay
|
||||
* teardown of the inode.
|
||||
*/
|
||||
if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip))
|
||||
xfs_filestream_deassociate(ip);
|
||||
|
||||
/*
|
||||
* If we previously truncated this file and removed old data
|
||||
* in the process, we want to initiate "early" writeout on
|
||||
* the last close. This is an attempt to combat the notorious
|
||||
* NULL files problem which is particularly noticable from a
|
||||
* truncate down, buffered (re-)write (delalloc), followed by
|
||||
* a crash. What we are effectively doing here is
|
||||
* significantly reducing the time window where we'd otherwise
|
||||
* be exposed to that problem.
|
||||
*/
|
||||
if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
|
||||
bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
|
||||
}
|
||||
|
||||
#ifdef HAVE_REFCACHE
|
||||
/* If we are in the NFS reference cache then don't do this now */
|
||||
if (ip->i_refcache)
|
||||
|
@ -1573,7 +1577,8 @@ xfs_release(
|
|||
(ip->i_df.if_flags & XFS_IFEXTENTS)) &&
|
||||
(!(ip->i_d.di_flags &
|
||||
(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
|
||||
if ((error = xfs_inactive_free_eofblocks(mp, ip)))
|
||||
error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
|
||||
if (error)
|
||||
return error;
|
||||
/* Update linux inode block count after free above */
|
||||
vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
|
||||
|
@ -1654,7 +1659,8 @@ xfs_inactive(
|
|||
(!(ip->i_d.di_flags &
|
||||
(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
|
||||
(ip->i_delayed_blks != 0)))) {
|
||||
if ((error = xfs_inactive_free_eofblocks(mp, ip)))
|
||||
error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
|
||||
if (error)
|
||||
return VN_INACTIVE_CACHE;
|
||||
/* Update linux inode block count after free above */
|
||||
vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
|
||||
|
@ -1680,6 +1686,7 @@ xfs_inactive(
|
|||
|
||||
error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
|
||||
if (error) {
|
||||
xfs_trans_cancel(tp, 0);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
return VN_INACTIVE_CACHE;
|
||||
}
|
||||
|
@ -2217,9 +2224,9 @@ static inline int
|
|||
xfs_lock_inumorder(int lock_mode, int subclass)
|
||||
{
|
||||
if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
|
||||
lock_mode |= (subclass + XFS_IOLOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
|
||||
lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
|
||||
if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))
|
||||
lock_mode |= (subclass + XFS_ILOCK_INUMORDER) << XFS_ILOCK_SHIFT;
|
||||
lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT;
|
||||
|
||||
return lock_mode;
|
||||
}
|
||||
|
@ -2546,6 +2553,15 @@ xfs_remove(
|
|||
*/
|
||||
xfs_refcache_purge_ip(ip);
|
||||
|
||||
/*
|
||||
* If we are using filestreams, kill the stream association.
|
||||
* If the file is still open it may get a new one but that
|
||||
* will get killed on last close in xfs_close() so we don't
|
||||
* have to worry about that.
|
||||
*/
|
||||
if (link_zero && xfs_inode_is_filestream(ip))
|
||||
xfs_filestream_deassociate(ip);
|
||||
|
||||
vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
|
||||
|
||||
/*
|
||||
|
@ -4047,22 +4063,16 @@ xfs_alloc_file_space(
|
|||
if (XFS_FORCED_SHUTDOWN(mp))
|
||||
return XFS_ERROR(EIO);
|
||||
|
||||
rt = XFS_IS_REALTIME_INODE(ip);
|
||||
if (unlikely(rt)) {
|
||||
if (!(extsz = ip->i_d.di_extsize))
|
||||
extsz = mp->m_sb.sb_rextsize;
|
||||
} else {
|
||||
extsz = ip->i_d.di_extsize;
|
||||
}
|
||||
|
||||
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
|
||||
return error;
|
||||
|
||||
if (len <= 0)
|
||||
return XFS_ERROR(EINVAL);
|
||||
|
||||
rt = XFS_IS_REALTIME_INODE(ip);
|
||||
extsz = xfs_get_extsz_hint(ip);
|
||||
|
||||
count = len;
|
||||
error = 0;
|
||||
imapp = &imaps[0];
|
||||
nimaps = 1;
|
||||
bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
|
||||
|
@ -4678,7 +4688,6 @@ xfs_change_file_space(
|
|||
bhv_vnodeops_t xfs_vnodeops = {
|
||||
BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
|
||||
.vop_open = xfs_open,
|
||||
.vop_close = xfs_close,
|
||||
.vop_read = xfs_read,
|
||||
#ifdef HAVE_SPLICE
|
||||
.vop_splice_read = xfs_splice_read,
|
||||
|
|
|
@ -151,6 +151,7 @@ int radix_tree_preload(gfp_t gfp_mask)
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(radix_tree_preload);
|
||||
|
||||
static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
|
||||
int offset)
|
||||
|
|
Загрузка…
Ссылка в новой задаче