mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
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:
@@ -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).
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user