Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs

* 'for-linus' of git://oss.sgi.com/xfs/xfs: (61 commits)
  Revert "xfs: increase the maximum number of supported ACL entries"
  xfs: cleanup uuid handling
  xfs: remove m_attroffset
  xfs: fix various typos
  xfs: pagecache usage optimization
  xfs: remove m_litino
  xfs: kill ino64 mount option
  xfs: kill mutex_t typedef
  xfs: increase the maximum number of supported ACL entries
  xfs: factor out code to find the longest free extent in the AG
  xfs: kill VN_BAD
  xfs: kill vn_atime_* helpers.
  xfs: cleanup xlog_bread
  xfs: cleanup xlog_recover_do_trans
  xfs: remove another leftover of the old inode log item format
  xfs: cleanup log unmount handling
  Fix xfs debug build breakage by pushing xfs_error.h after
  xfs: include header files for prototypes
  xfs: make symbols static
  xfs: move declaration to header file
  ...
This commit is contained in:
Linus Torvalds 2009-04-03 09:52:29 -07:00
commit ac7c1a776d
69 changed files with 1026 additions and 1594 deletions

View file

@ -4969,7 +4969,8 @@ S: Supported
XFS FILESYSTEM XFS FILESYSTEM
P: Silicon Graphics Inc P: Silicon Graphics Inc
P: Bill O'Donnell P: Felix Blyakher
M: felixb@sgi.com
M: xfs-masters@oss.sgi.com M: xfs-masters@oss.sgi.com
L: xfs@oss.sgi.com L: xfs@oss.sgi.com
W: http://oss.sgi.com/projects/xfs W: http://oss.sgi.com/projects/xfs

View file

@ -33,6 +33,7 @@ xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \
xfs_qm_syscalls.o \ xfs_qm_syscalls.o \
xfs_qm_bhv.o \ xfs_qm_bhv.o \
xfs_qm.o) xfs_qm.o)
xfs-$(CONFIG_XFS_QUOTA) += linux-2.6/xfs_quotaops.o
ifeq ($(CONFIG_XFS_QUOTA),y) ifeq ($(CONFIG_XFS_QUOTA),y)
xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o

View file

@ -1,25 +0,0 @@
/*
* Copyright (c) 2000-2003,2005 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_SUPPORT_MUTEX_H__
#define __XFS_SUPPORT_MUTEX_H__
#include <linux/mutex.h>
typedef struct mutex mutex_t;
#endif /* __XFS_SUPPORT_MUTEX_H__ */

View file

@ -1623,4 +1623,5 @@ const struct address_space_operations xfs_address_space_operations = {
.bmap = xfs_vm_bmap, .bmap = xfs_vm_bmap,
.direct_IO = xfs_vm_direct_IO, .direct_IO = xfs_vm_direct_IO,
.migratepage = buffer_migrate_page, .migratepage = buffer_migrate_page,
.is_partially_uptodate = block_is_partially_uptodate,
}; };

View file

@ -34,6 +34,7 @@
#include "xfs_dir2_sf.h" #include "xfs_dir2_sf.h"
#include "xfs_dinode.h" #include "xfs_dinode.h"
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_ioctl.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_ialloc.h" #include "xfs_ialloc.h"
#include "xfs_rtalloc.h" #include "xfs_rtalloc.h"
@ -78,92 +79,74 @@ xfs_find_handle(
int hsize; int hsize;
xfs_handle_t handle; xfs_handle_t handle;
struct inode *inode; struct inode *inode;
struct file *file = NULL;
struct path path;
int error;
struct xfs_inode *ip;
memset((char *)&handle, 0, sizeof(handle)); if (cmd == XFS_IOC_FD_TO_HANDLE) {
switch (cmd) {
case XFS_IOC_PATH_TO_FSHANDLE:
case XFS_IOC_PATH_TO_HANDLE: {
struct path path;
int error = user_lpath((const char __user *)hreq->path, &path);
if (error)
return error;
ASSERT(path.dentry);
ASSERT(path.dentry->d_inode);
inode = igrab(path.dentry->d_inode);
path_put(&path);
break;
}
case XFS_IOC_FD_TO_HANDLE: {
struct file *file;
file = fget(hreq->fd); file = fget(hreq->fd);
if (!file) if (!file)
return -EBADF; return -EBADF;
inode = file->f_path.dentry->d_inode;
ASSERT(file->f_path.dentry); } else {
ASSERT(file->f_path.dentry->d_inode); error = user_lpath((const char __user *)hreq->path, &path);
inode = igrab(file->f_path.dentry->d_inode); if (error)
fput(file); return error;
break; inode = path.dentry->d_inode;
} }
ip = XFS_I(inode);
default: /*
ASSERT(0); * We can only generate handles for inodes residing on a XFS filesystem,
return -XFS_ERROR(EINVAL); * and only for regular files, directories or symbolic links.
} */
error = -EINVAL;
if (inode->i_sb->s_magic != XFS_SB_MAGIC)
goto out_put;
if (inode->i_sb->s_magic != XFS_SB_MAGIC) { error = -EBADF;
/* we're not in XFS anymore, Toto */ if (!S_ISREG(inode->i_mode) &&
iput(inode); !S_ISDIR(inode->i_mode) &&
return -XFS_ERROR(EINVAL); !S_ISLNK(inode->i_mode))
} goto out_put;
switch (inode->i_mode & S_IFMT) {
case S_IFREG:
case S_IFDIR:
case S_IFLNK:
break;
default:
iput(inode);
return -XFS_ERROR(EBADF);
}
/* now we can grab the fsid */ memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
sizeof(xfs_fsid_t));
hsize = sizeof(xfs_fsid_t);
if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
xfs_inode_t *ip = XFS_I(inode); /*
* This handle only contains an fsid, zero the rest.
*/
memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
hsize = sizeof(xfs_fsid_t);
} else {
int lock_mode; int lock_mode;
/* need to get access to the xfs_inode to read the generation */
lock_mode = xfs_ilock_map_shared(ip); lock_mode = xfs_ilock_map_shared(ip);
/* fill in fid section of handle from inode */
handle.ha_fid.fid_len = sizeof(xfs_fid_t) - handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
sizeof(handle.ha_fid.fid_len); sizeof(handle.ha_fid.fid_len);
handle.ha_fid.fid_pad = 0; handle.ha_fid.fid_pad = 0;
handle.ha_fid.fid_gen = ip->i_d.di_gen; handle.ha_fid.fid_gen = ip->i_d.di_gen;
handle.ha_fid.fid_ino = ip->i_ino; handle.ha_fid.fid_ino = ip->i_ino;
xfs_iunlock_map_shared(ip, lock_mode); xfs_iunlock_map_shared(ip, lock_mode);
hsize = XFS_HSIZE(handle); hsize = XFS_HSIZE(handle);
} }
/* now copy our handle into the user buffer & write out the size */ error = -EFAULT;
if (copy_to_user(hreq->ohandle, &handle, hsize) || if (copy_to_user(hreq->ohandle, &handle, hsize) ||
copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) { copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
iput(inode); goto out_put;
return -XFS_ERROR(EFAULT);
}
iput(inode); error = 0;
return 0;
out_put:
if (cmd == XFS_IOC_FD_TO_HANDLE)
fput(file);
else
path_put(&path);
return error;
} }
/* /*

View file

@ -211,8 +211,13 @@ xfs_vn_mknod(
* Irix uses Missed'em'V split, but doesn't want to see * Irix uses Missed'em'V split, but doesn't want to see
* the upper 5 bits of (14bit) major. * the upper 5 bits of (14bit) major.
*/ */
if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)) if (S_ISCHR(mode) || S_ISBLK(mode)) {
return -EINVAL; if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff))
return -EINVAL;
rdev = sysv_encode_dev(rdev);
} else {
rdev = 0;
}
if (test_default_acl && test_default_acl(dir)) { if (test_default_acl && test_default_acl(dir)) {
if (!_ACL_ALLOC(default_acl)) { if (!_ACL_ALLOC(default_acl)) {
@ -224,28 +229,11 @@ xfs_vn_mknod(
} }
} }
xfs_dentry_to_name(&name, dentry);
if (IS_POSIXACL(dir) && !default_acl) if (IS_POSIXACL(dir) && !default_acl)
mode &= ~current_umask(); mode &= ~current_umask();
switch (mode & S_IFMT) { xfs_dentry_to_name(&name, dentry);
case S_IFCHR: error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL);
case S_IFBLK:
case S_IFIFO:
case S_IFSOCK:
rdev = sysv_encode_dev(rdev);
case S_IFREG:
error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL);
break;
case S_IFDIR:
error = xfs_mkdir(XFS_I(dir), &name, mode, &ip, NULL);
break;
default:
error = EINVAL;
break;
}
if (unlikely(error)) if (unlikely(error))
goto out_free_acl; goto out_free_acl;
@ -553,9 +541,6 @@ xfs_vn_getattr(
stat->uid = ip->i_d.di_uid; stat->uid = ip->i_d.di_uid;
stat->gid = ip->i_d.di_gid; stat->gid = ip->i_d.di_gid;
stat->ino = ip->i_ino; stat->ino = ip->i_ino;
#if XFS_BIG_INUMS
stat->ino += mp->m_inoadd;
#endif
stat->atime = inode->i_atime; stat->atime = inode->i_atime;
stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec; stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec;
stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;

View file

@ -38,7 +38,6 @@
#include <kmem.h> #include <kmem.h>
#include <mrlock.h> #include <mrlock.h>
#include <sv.h> #include <sv.h>
#include <mutex.h>
#include <time.h> #include <time.h>
#include <support/ktrace.h> #include <support/ktrace.h>
@ -51,6 +50,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/errno.h> #include <linux/errno.h>
@ -147,17 +147,6 @@
#define SYNCHRONIZE() barrier() #define SYNCHRONIZE() barrier()
#define __return_address __builtin_return_address(0) #define __return_address __builtin_return_address(0)
/*
* IRIX (BSD) quotactl makes use of separate commands for user/group,
* whereas on Linux the syscall encodes this information into the cmd
* field (see the QCMD macro in quota.h). These macros help keep the
* code portable - they are not visible from the syscall interface.
*/
#define Q_XSETGQLIM XQM_CMD(8) /* set groups disk limits */
#define Q_XGETGQUOTA XQM_CMD(9) /* get groups disk limits */
#define Q_XSETPQLIM XQM_CMD(10) /* set projects disk limits */
#define Q_XGETPQUOTA XQM_CMD(11) /* get projects disk limits */
#define dfltprid 0 #define dfltprid 0
#define MAXPATHLEN 1024 #define MAXPATHLEN 1024

View file

@ -0,0 +1,157 @@
/*
* Copyright (c) 2008, Christoph Hellwig
* 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_dmapi.h"
#include "xfs_sb.h"
#include "xfs_inum.h"
#include "xfs_ag.h"
#include "xfs_mount.h"
#include "xfs_quota.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_bmap_btree.h"
#include "xfs_inode.h"
#include "quota/xfs_qm.h"
#include <linux/quota.h>
STATIC int
xfs_quota_type(int type)
{
switch (type) {
case USRQUOTA:
return XFS_DQ_USER;
case GRPQUOTA:
return XFS_DQ_GROUP;
default:
return XFS_DQ_PROJ;
}
}
STATIC int
xfs_fs_quota_sync(
struct super_block *sb,
int type)
{
struct xfs_mount *mp = XFS_M(sb);
if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
return -xfs_sync_inodes(mp, SYNC_DELWRI);
}
STATIC int
xfs_fs_get_xstate(
struct super_block *sb,
struct fs_quota_stat *fqs)
{
struct xfs_mount *mp = XFS_M(sb);
if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
return -xfs_qm_scall_getqstat(mp, fqs);
}
STATIC int
xfs_fs_set_xstate(
struct super_block *sb,
unsigned int uflags,
int op)
{
struct xfs_mount *mp = XFS_M(sb);
unsigned int flags = 0;
if (sb->s_flags & MS_RDONLY)
return -EROFS;
if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (uflags & XFS_QUOTA_UDQ_ACCT)
flags |= XFS_UQUOTA_ACCT;
if (uflags & XFS_QUOTA_PDQ_ACCT)
flags |= XFS_PQUOTA_ACCT;
if (uflags & XFS_QUOTA_GDQ_ACCT)
flags |= XFS_GQUOTA_ACCT;
if (uflags & XFS_QUOTA_UDQ_ENFD)
flags |= XFS_UQUOTA_ENFD;
if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
flags |= XFS_OQUOTA_ENFD;
switch (op) {
case Q_XQUOTAON:
return -xfs_qm_scall_quotaon(mp, flags);
case Q_XQUOTAOFF:
if (!XFS_IS_QUOTA_ON(mp))
return -EINVAL;
return -xfs_qm_scall_quotaoff(mp, flags);
case Q_XQUOTARM:
if (XFS_IS_QUOTA_ON(mp))
return -EINVAL;
return -xfs_qm_scall_trunc_qfiles(mp, flags);
}
return -EINVAL;
}
STATIC int
xfs_fs_get_xquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
struct xfs_mount *mp = XFS_M(sb);
if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;
return -xfs_qm_scall_getquota(mp, id, xfs_quota_type(type), fdq);
}
STATIC int
xfs_fs_set_xquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
struct xfs_mount *mp = XFS_M(sb);
if (sb->s_flags & MS_RDONLY)
return -EROFS;
if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
return -xfs_qm_scall_setqlim(mp, id, xfs_quota_type(type), fdq);
}
struct quotactl_ops xfs_quotactl_operations = {
.quota_sync = xfs_fs_quota_sync,
.get_xstate = xfs_fs_get_xstate,
.set_xstate = xfs_fs_set_xstate,
.get_xquota = xfs_fs_get_xquota,
.set_xquota = xfs_fs_set_xquota,
};

View file

@ -68,7 +68,6 @@
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/parser.h> #include <linux/parser.h>
static struct quotactl_ops xfs_quotactl_operations;
static struct super_operations xfs_super_operations; static struct super_operations xfs_super_operations;
static kmem_zone_t *xfs_ioend_zone; static kmem_zone_t *xfs_ioend_zone;
mempool_t *xfs_ioend_pool; mempool_t *xfs_ioend_pool;
@ -79,7 +78,6 @@ mempool_t *xfs_ioend_pool;
#define MNTOPT_RTDEV "rtdev" /* realtime I/O device */ #define MNTOPT_RTDEV "rtdev" /* realtime I/O device */
#define MNTOPT_BIOSIZE "biosize" /* log2 of preferred buffered io size */ #define MNTOPT_BIOSIZE "biosize" /* log2 of preferred buffered io size */
#define MNTOPT_WSYNC "wsync" /* safe-mode nfs compatible mount */ #define MNTOPT_WSYNC "wsync" /* safe-mode nfs compatible mount */
#define MNTOPT_INO64 "ino64" /* force inodes into 64-bit range */
#define MNTOPT_NOALIGN "noalign" /* turn off stripe alignment */ #define MNTOPT_NOALIGN "noalign" /* turn off stripe alignment */
#define MNTOPT_SWALLOC "swalloc" /* turn on stripe width allocation */ #define MNTOPT_SWALLOC "swalloc" /* turn on stripe width allocation */
#define MNTOPT_SUNIT "sunit" /* data volume stripe unit */ #define MNTOPT_SUNIT "sunit" /* data volume stripe unit */
@ -180,7 +178,7 @@ xfs_parseargs(
int dswidth = 0; int dswidth = 0;
int iosize = 0; int iosize = 0;
int dmapi_implies_ikeep = 1; int dmapi_implies_ikeep = 1;
uchar_t iosizelog = 0; __uint8_t iosizelog = 0;
/* /*
* Copy binary VFS mount flags we are interested in. * Copy binary VFS mount flags we are interested in.
@ -291,16 +289,6 @@ xfs_parseargs(
mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC;
} else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
mp->m_flags |= XFS_MOUNT_NORECOVERY; mp->m_flags |= XFS_MOUNT_NORECOVERY;
} else if (!strcmp(this_char, MNTOPT_INO64)) {
#if XFS_BIG_INUMS
mp->m_flags |= XFS_MOUNT_INO64;
mp->m_inoadd = XFS_INO64_OFFSET;
#else
cmn_err(CE_WARN,
"XFS: %s option not allowed on this system",
this_char);
return EINVAL;
#endif
} else if (!strcmp(this_char, MNTOPT_NOALIGN)) { } else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
mp->m_flags |= XFS_MOUNT_NOALIGN; mp->m_flags |= XFS_MOUNT_NOALIGN;
} else if (!strcmp(this_char, MNTOPT_SWALLOC)) { } else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
@ -529,7 +517,6 @@ xfs_showargs(
/* the few simple ones we can get from the mount struct */ /* the few simple ones we can get from the mount struct */
{ XFS_MOUNT_IKEEP, "," MNTOPT_IKEEP }, { XFS_MOUNT_IKEEP, "," MNTOPT_IKEEP },
{ XFS_MOUNT_WSYNC, "," MNTOPT_WSYNC }, { XFS_MOUNT_WSYNC, "," MNTOPT_WSYNC },
{ XFS_MOUNT_INO64, "," MNTOPT_INO64 },
{ XFS_MOUNT_NOALIGN, "," MNTOPT_NOALIGN }, { XFS_MOUNT_NOALIGN, "," MNTOPT_NOALIGN },
{ XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC }, { XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC },
{ XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID },
@ -634,7 +621,7 @@ xfs_max_file_offset(
return (((__uint64_t)pagefactor) << bitshift) - 1; return (((__uint64_t)pagefactor) << bitshift) - 1;
} }
int STATIC int
xfs_blkdev_get( xfs_blkdev_get(
xfs_mount_t *mp, xfs_mount_t *mp,
const char *name, const char *name,
@ -651,7 +638,7 @@ xfs_blkdev_get(
return -error; return -error;
} }
void STATIC void
xfs_blkdev_put( xfs_blkdev_put(
struct block_device *bdev) struct block_device *bdev)
{ {
@ -872,7 +859,7 @@ xfsaild_wakeup(
wake_up_process(ailp->xa_task); wake_up_process(ailp->xa_task);
} }
int STATIC int
xfsaild( xfsaild(
void *data) void *data)
{ {
@ -990,26 +977,57 @@ xfs_fs_write_inode(
int sync) int sync)
{ {
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
int error = 0; int error = 0;
int flags = 0;
xfs_itrace_entry(ip); xfs_itrace_entry(ip);
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
if (sync) { if (sync) {
error = xfs_wait_on_pages(ip, 0, -1); error = xfs_wait_on_pages(ip, 0, -1);
if (error) if (error)
goto out_error; goto out;
flags |= FLUSH_SYNC;
} }
error = xfs_inode_flush(ip, flags);
out_error: /*
* Bypass inodes which have already been cleaned by
* the inode flush clustering code inside xfs_iflush
*/
if (xfs_inode_clean(ip))
goto out;
/*
* We make this non-blocking if the inode is contended, return
* EAGAIN to indicate to the caller that they did not succeed.
* This prevents the flush path from blocking on inodes inside
* another operation right now, they get caught later by xfs_sync.
*/
if (sync) {
xfs_ilock(ip, XFS_ILOCK_SHARED);
xfs_iflock(ip);
error = xfs_iflush(ip, XFS_IFLUSH_SYNC);
} else {
error = EAGAIN;
if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED))
goto out;
if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip))
goto out_unlock;
error = xfs_iflush(ip, XFS_IFLUSH_ASYNC_NOBLOCK);
}
out_unlock:
xfs_iunlock(ip, XFS_ILOCK_SHARED);
out:
/* /*
* if we failed to write out the inode then mark * if we failed to write out the inode then mark
* it dirty again so we'll try again later. * it dirty again so we'll try again later.
*/ */
if (error) if (error)
xfs_mark_inode_dirty_sync(ip); xfs_mark_inode_dirty_sync(ip);
return -error; return -error;
} }
@ -1169,18 +1187,12 @@ xfs_fs_statfs(
statp->f_bfree = statp->f_bavail = statp->f_bfree = statp->f_bavail =
sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
fakeinos = statp->f_bfree << sbp->sb_inopblog; fakeinos = statp->f_bfree << sbp->sb_inopblog;
#if XFS_BIG_INUMS
fakeinos += mp->m_inoadd;
#endif
statp->f_files = statp->f_files =
MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER); MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
if (mp->m_maxicount) if (mp->m_maxicount)
#if XFS_BIG_INUMS statp->f_files = min_t(typeof(statp->f_files),
if (!mp->m_inoadd) statp->f_files,
#endif mp->m_maxicount);
statp->f_files = min_t(typeof(statp->f_files),
statp->f_files,
mp->m_maxicount);
statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree); statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
spin_unlock(&mp->m_sb_lock); spin_unlock(&mp->m_sb_lock);
@ -1302,57 +1314,6 @@ xfs_fs_show_options(
return -xfs_showargs(XFS_M(mnt->mnt_sb), m); return -xfs_showargs(XFS_M(mnt->mnt_sb), m);
} }
STATIC int
xfs_fs_quotasync(
struct super_block *sb,
int type)
{
return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL);
}
STATIC int
xfs_fs_getxstate(
struct super_block *sb,
struct fs_quota_stat *fqs)
{
return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
}
STATIC int
xfs_fs_setxstate(
struct super_block *sb,
unsigned int flags,
int op)
{
return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags);
}
STATIC int
xfs_fs_getxquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XGETQUOTA :
((type == GRPQUOTA) ? Q_XGETGQUOTA :
Q_XGETPQUOTA), id, (caddr_t)fdq);
}
STATIC int
xfs_fs_setxquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XSETQLIM :
((type == GRPQUOTA) ? Q_XSETGQLIM :
Q_XSETPQLIM), id, (caddr_t)fdq);
}
/* /*
* This function fills in xfs_mount_t fields based on mount args. * This function fills in xfs_mount_t fields based on mount args.
* Note: the superblock _has_ now been read in. * Note: the superblock _has_ now been read in.
@ -1435,7 +1396,9 @@ xfs_fs_fill_super(
sb_min_blocksize(sb, BBSIZE); sb_min_blocksize(sb, BBSIZE);
sb->s_xattr = xfs_xattr_handlers; sb->s_xattr = xfs_xattr_handlers;
sb->s_export_op = &xfs_export_operations; sb->s_export_op = &xfs_export_operations;
#ifdef CONFIG_XFS_QUOTA
sb->s_qcop = &xfs_quotactl_operations; sb->s_qcop = &xfs_quotactl_operations;
#endif
sb->s_op = &xfs_super_operations; sb->s_op = &xfs_super_operations;
error = xfs_dmops_get(mp); error = xfs_dmops_get(mp);
@ -1578,14 +1541,6 @@ static struct super_operations xfs_super_operations = {
.show_options = xfs_fs_show_options, .show_options = xfs_fs_show_options,
}; };
static struct quotactl_ops xfs_quotactl_operations = {
.quota_sync = xfs_fs_quotasync,
.get_xstate = xfs_fs_getxstate,
.set_xstate = xfs_fs_setxstate,
.get_xquota = xfs_fs_getxquota,
.set_xquota = xfs_fs_setxquota,
};
static struct file_system_type xfs_fs_type = { static struct file_system_type xfs_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "xfs", .name = "xfs",

View file

@ -93,6 +93,7 @@ extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
extern const struct export_operations xfs_export_operations; extern const struct export_operations xfs_export_operations;
extern struct xattr_handler *xfs_xattr_handlers[]; extern struct xattr_handler *xfs_xattr_handlers[];
extern struct quotactl_ops xfs_quotactl_operations;
#define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info))

View file

@ -19,6 +19,7 @@
#define XFS_SYNC_H 1 #define XFS_SYNC_H 1
struct xfs_mount; struct xfs_mount;
struct xfs_perag;
typedef struct bhv_vfs_sync_work { typedef struct bhv_vfs_sync_work {
struct list_head w_list; struct list_head w_list;

View file

@ -40,11 +40,6 @@ struct attrlist_cursor_kern;
#define IO_ISDIRECT 0x00004 /* bypass page cache */ #define IO_ISDIRECT 0x00004 /* bypass page cache */
#define IO_INVIS 0x00020 /* don't update inode timestamps */ #define IO_INVIS 0x00020 /* don't update inode timestamps */
/*
* Flags for xfs_inode_flush
*/
#define FLUSH_SYNC 1 /* wait for flush to complete */
/* /*
* Flush/Invalidate options for vop_toss/flush/flushinval_pages. * Flush/Invalidate options for vop_toss/flush/flushinval_pages.
*/ */
@ -54,33 +49,6 @@ struct attrlist_cursor_kern;
Prevent VM access to the pages until Prevent VM access to the pages until
the operation completes. */ the operation completes. */
/*
* Dealing with bad inodes
*/
static inline int VN_BAD(struct inode *vp)
{
return is_bad_inode(vp);
}
/*
* Extracting atime values in various formats
*/
static inline void vn_atime_to_bstime(struct inode *vp, xfs_bstime_t *bs_atime)
{
bs_atime->tv_sec = vp->i_atime.tv_sec;
bs_atime->tv_nsec = vp->i_atime.tv_nsec;
}
static inline void vn_atime_to_timespec(struct inode *vp, struct timespec *ts)
{
*ts = vp->i_atime;
}
static inline void vn_atime_to_time_t(struct inode *vp, time_t *tt)
{
*tt = vp->i_atime.tv_sec;
}
/* /*
* Some useful predicates. * Some useful predicates.
*/ */

View file

@ -804,7 +804,7 @@ xfs_qm_dqlookup(
uint flist_locked; uint flist_locked;
xfs_dquot_t *d; xfs_dquot_t *d;
ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); ASSERT(mutex_is_locked(&qh->qh_lock));
flist_locked = B_FALSE; flist_locked = B_FALSE;
@ -877,7 +877,7 @@ xfs_qm_dqlookup(
/* /*
* move the dquot to the front of the hashchain * move the dquot to the front of the hashchain
*/ */
ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); ASSERT(mutex_is_locked(&qh->qh_lock));
if (dqp->HL_PREVP != &qh->qh_next) { if (dqp->HL_PREVP != &qh->qh_next) {
xfs_dqtrace_entry(dqp, xfs_dqtrace_entry(dqp,
"DQLOOKUP: HASH MOVETOFRONT"); "DQLOOKUP: HASH MOVETOFRONT");
@ -892,13 +892,13 @@ xfs_qm_dqlookup(
} }
xfs_dqtrace_entry(dqp, "LOOKUP END"); xfs_dqtrace_entry(dqp, "LOOKUP END");
*O_dqpp = dqp; *O_dqpp = dqp;
ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); ASSERT(mutex_is_locked(&qh->qh_lock));
return (0); return (0);
} }
} }
*O_dqpp = NULL; *O_dqpp = NULL;
ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); ASSERT(mutex_is_locked(&qh->qh_lock));
return (1); return (1);
} }
@ -956,7 +956,7 @@ xfs_qm_dqget(
ASSERT(ip->i_gdquot == NULL); ASSERT(ip->i_gdquot == NULL);
} }
#endif #endif
XFS_DQ_HASH_LOCK(h); mutex_lock(&h->qh_lock);
/* /*
* Look in the cache (hashtable). * Look in the cache (hashtable).
@ -971,7 +971,7 @@ xfs_qm_dqget(
*/ */
ASSERT(*O_dqpp); ASSERT(*O_dqpp);
ASSERT(XFS_DQ_IS_LOCKED(*O_dqpp)); ASSERT(XFS_DQ_IS_LOCKED(*O_dqpp));
XFS_DQ_HASH_UNLOCK(h); mutex_unlock(&h->qh_lock);
xfs_dqtrace_entry(*O_dqpp, "DQGET DONE (FROM CACHE)"); xfs_dqtrace_entry(*O_dqpp, "DQGET DONE (FROM CACHE)");
return (0); /* success */ return (0); /* success */
} }
@ -991,7 +991,7 @@ xfs_qm_dqget(
* we don't keep the lock across a disk read * we don't keep the lock across a disk read
*/ */
version = h->qh_version; version = h->qh_version;
XFS_DQ_HASH_UNLOCK(h); mutex_unlock(&h->qh_lock);
/* /*
* Allocate the dquot on the kernel heap, and read the ondisk * Allocate the dquot on the kernel heap, and read the ondisk
@ -1056,7 +1056,7 @@ xfs_qm_dqget(
/* /*
* Hashlock comes after ilock in lock order * Hashlock comes after ilock in lock order
*/ */
XFS_DQ_HASH_LOCK(h); mutex_lock(&h->qh_lock);
if (version != h->qh_version) { if (version != h->qh_version) {
xfs_dquot_t *tmpdqp; xfs_dquot_t *tmpdqp;
/* /*
@ -1072,7 +1072,7 @@ xfs_qm_dqget(
* and start over. * and start over.
*/ */
xfs_qm_dqput(tmpdqp); xfs_qm_dqput(tmpdqp);
XFS_DQ_HASH_UNLOCK(h); mutex_unlock(&h->qh_lock);
xfs_qm_dqdestroy(dqp); xfs_qm_dqdestroy(dqp);
XQM_STATS_INC(xqmstats.xs_qm_dquot_dups); XQM_STATS_INC(xqmstats.xs_qm_dquot_dups);
goto again; goto again;
@ -1083,7 +1083,7 @@ xfs_qm_dqget(
* Put the dquot at the beginning of the hash-chain and mp's list * Put the dquot at the beginning of the hash-chain and mp's list
* LOCK ORDER: hashlock, freelistlock, mplistlock, udqlock, gdqlock .. * LOCK ORDER: hashlock, freelistlock, mplistlock, udqlock, gdqlock ..
*/ */
ASSERT(XFS_DQ_IS_HASH_LOCKED(h)); ASSERT(mutex_is_locked(&h->qh_lock));
dqp->q_hash = h; dqp->q_hash = h;
XQM_HASHLIST_INSERT(h, dqp); XQM_HASHLIST_INSERT(h, dqp);
@ -1102,7 +1102,7 @@ xfs_qm_dqget(
XQM_MPLIST_INSERT(&(XFS_QI_MPL_LIST(mp)), dqp); XQM_MPLIST_INSERT(&(XFS_QI_MPL_LIST(mp)), dqp);
xfs_qm_mplist_unlock(mp); xfs_qm_mplist_unlock(mp);
XFS_DQ_HASH_UNLOCK(h); mutex_unlock(&h->qh_lock);
dqret: dqret:
ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL));
xfs_dqtrace_entry(dqp, "DQGET DONE"); xfs_dqtrace_entry(dqp, "DQGET DONE");
@ -1440,7 +1440,7 @@ xfs_qm_dqpurge(
xfs_mount_t *mp = dqp->q_mount; xfs_mount_t *mp = dqp->q_mount;
ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp)); ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp));
ASSERT(XFS_DQ_IS_HASH_LOCKED(dqp->q_hash)); ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock));
xfs_dqlock(dqp); xfs_dqlock(dqp);
/* /*
@ -1453,7 +1453,7 @@ xfs_qm_dqpurge(
*/ */
if (dqp->q_nrefs != 0) { if (dqp->q_nrefs != 0) {
xfs_dqunlock(dqp); xfs_dqunlock(dqp);
XFS_DQ_HASH_UNLOCK(dqp->q_hash); mutex_unlock(&dqp->q_hash->qh_lock);
return (1); return (1);
} }
@ -1517,7 +1517,7 @@ xfs_qm_dqpurge(
memset(&dqp->q_core, 0, sizeof(dqp->q_core)); memset(&dqp->q_core, 0, sizeof(dqp->q_core));
xfs_dqfunlock(dqp); xfs_dqfunlock(dqp);
xfs_dqunlock(dqp); xfs_dqunlock(dqp);
XFS_DQ_HASH_UNLOCK(thishash); mutex_unlock(&thishash->qh_lock);
return (0); return (0);
} }

View file

@ -34,7 +34,7 @@
*/ */
typedef struct xfs_dqhash { typedef struct xfs_dqhash {
struct xfs_dquot *qh_next; struct xfs_dquot *qh_next;
mutex_t qh_lock; struct mutex qh_lock;
uint qh_version; /* ever increasing version */ uint qh_version; /* ever increasing version */
uint qh_nelems; /* number of dquots on the list */ uint qh_nelems; /* number of dquots on the list */
} xfs_dqhash_t; } xfs_dqhash_t;
@ -81,7 +81,7 @@ typedef struct xfs_dquot {
xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */
xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */
xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */
mutex_t q_qlock; /* quota lock */ struct mutex q_qlock; /* quota lock */
struct completion q_flush; /* flush completion queue */ struct completion q_flush; /* flush completion queue */
atomic_t q_pincount; /* dquot pin count */ atomic_t q_pincount; /* dquot pin count */
wait_queue_head_t q_pinwait; /* dquot pinning wait queue */ wait_queue_head_t q_pinwait; /* dquot pinning wait queue */
@ -109,19 +109,6 @@ enum {
#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) #define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++)
#ifdef DEBUG
static inline int
XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
{
if (mutex_trylock(&dqp->q_qlock)) {
mutex_unlock(&dqp->q_qlock);
return 0;
}
return 1;
}
#endif
/* /*
* Manage the q_flush completion queue embedded in the dquot. This completion * Manage the q_flush completion queue embedded in the dquot. This completion
* queue synchronizes processes attempting to flush the in-core dquot back to * queue synchronizes processes attempting to flush the in-core dquot back to
@ -142,6 +129,7 @@ static inline void xfs_dqfunlock(xfs_dquot_t *dqp)
complete(&dqp->q_flush); complete(&dqp->q_flush);
} }
#define XFS_DQ_IS_LOCKED(dqp) (mutex_is_locked(&((dqp)->q_qlock)))
#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp))
#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY)
#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)

View file

@ -55,7 +55,7 @@
* quota functionality, including maintaining the freelist and hash * quota functionality, including maintaining the freelist and hash
* tables of dquots. * tables of dquots.
*/ */
mutex_t xfs_Gqm_lock; struct mutex xfs_Gqm_lock;
struct xfs_qm *xfs_Gqm; struct xfs_qm *xfs_Gqm;
uint ndquot; uint ndquot;
@ -69,8 +69,6 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
STATIC void xfs_qm_freelist_init(xfs_frlist_t *); STATIC void xfs_qm_freelist_init(xfs_frlist_t *);
STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *); STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *);
STATIC int xfs_qm_mplist_nowait(xfs_mount_t *);
STATIC int xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
STATIC int xfs_qm_init_quotainos(xfs_mount_t *); STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
@ -82,7 +80,7 @@ static struct shrinker xfs_qm_shaker = {
}; };
#ifdef DEBUG #ifdef DEBUG
extern mutex_t qcheck_lock; extern struct mutex qcheck_lock;
#endif #endif
#ifdef QUOTADEBUG #ifdef QUOTADEBUG
@ -219,7 +217,7 @@ xfs_qm_hold_quotafs_ref(
* the structure could disappear between the entry to this routine and * the structure could disappear between the entry to this routine and
* a HOLD operation if not locked. * a HOLD operation if not locked.
*/ */
XFS_QM_LOCK(xfs_Gqm); mutex_lock(&xfs_Gqm_lock);
if (xfs_Gqm == NULL) if (xfs_Gqm == NULL)
xfs_Gqm = xfs_Gqm_init(); xfs_Gqm = xfs_Gqm_init();
@ -228,8 +226,8 @@ xfs_qm_hold_quotafs_ref(
* debugging and statistical purposes, but ... * debugging and statistical purposes, but ...
* Just take a reference and get out. * Just take a reference and get out.
*/ */
XFS_QM_HOLD(xfs_Gqm); xfs_Gqm->qm_nrefs++;
XFS_QM_UNLOCK(xfs_Gqm); mutex_unlock(&xfs_Gqm_lock);
return 0; return 0;
} }
@ -277,13 +275,12 @@ xfs_qm_rele_quotafs_ref(
* Destroy the entire XQM. If somebody mounts with quotaon, this'll * Destroy the entire XQM. If somebody mounts with quotaon, this'll
* be restarted. * be restarted.
*/ */
XFS_QM_LOCK(xfs_Gqm); mutex_lock(&xfs_Gqm_lock);
XFS_QM_RELE(xfs_Gqm); if (--xfs_Gqm->qm_nrefs == 0) {
if (xfs_Gqm->qm_nrefs == 0) {
xfs_qm_destroy(xfs_Gqm); xfs_qm_destroy(xfs_Gqm);
xfs_Gqm = NULL; xfs_Gqm = NULL;
} }
XFS_QM_UNLOCK(xfs_Gqm); mutex_unlock(&xfs_Gqm_lock);
} }
/* /*
@ -577,10 +574,10 @@ xfs_qm_dqpurge_int(
continue; continue;
} }
if (! xfs_qm_dqhashlock_nowait(dqp)) { if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
nrecl = XFS_QI_MPLRECLAIMS(mp); nrecl = XFS_QI_MPLRECLAIMS(mp);
xfs_qm_mplist_unlock(mp); xfs_qm_mplist_unlock(mp);
XFS_DQ_HASH_LOCK(dqp->q_hash); mutex_lock(&dqp->q_hash->qh_lock);
xfs_qm_mplist_lock(mp); xfs_qm_mplist_lock(mp);
/* /*
@ -590,7 +587,7 @@ xfs_qm_dqpurge_int(
* this point, but somebody might be taking things off. * this point, but somebody might be taking things off.
*/ */
if (nrecl != XFS_QI_MPLRECLAIMS(mp)) { if (nrecl != XFS_QI_MPLRECLAIMS(mp)) {
XFS_DQ_HASH_UNLOCK(dqp->q_hash); mutex_unlock(&dqp->q_hash->qh_lock);
goto again; goto again;
} }
} }
@ -632,7 +629,6 @@ xfs_qm_dqattach_one(
xfs_dqid_t id, xfs_dqid_t id,
uint type, uint type,
uint doalloc, uint doalloc,
uint dolock,
xfs_dquot_t *udqhint, /* hint */ xfs_dquot_t *udqhint, /* hint */
xfs_dquot_t **IO_idqpp) xfs_dquot_t **IO_idqpp)
{ {
@ -641,16 +637,16 @@ xfs_qm_dqattach_one(
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
error = 0; error = 0;
/* /*
* See if we already have it in the inode itself. IO_idqpp is * See if we already have it in the inode itself. IO_idqpp is
* &i_udquot or &i_gdquot. This made the code look weird, but * &i_udquot or &i_gdquot. This made the code look weird, but
* made the logic a lot simpler. * made the logic a lot simpler.
*/ */
if ((dqp = *IO_idqpp)) { dqp = *IO_idqpp;
if (dolock) if (dqp) {
xfs_dqlock(dqp);
xfs_dqtrace_entry(dqp, "DQATTACH: found in ip"); xfs_dqtrace_entry(dqp, "DQATTACH: found in ip");
goto done; return 0;
} }
/* /*
@ -659,38 +655,38 @@ xfs_qm_dqattach_one(
* lookup by dqid (xfs_qm_dqget) by caching a group dquot inside * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
* the user dquot. * the user dquot.
*/ */
ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); if (udqhint) {
if (udqhint && !dolock) ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
xfs_dqlock(udqhint); xfs_dqlock(udqhint);
/* /*
* No need to take dqlock to look at the id. * No need to take dqlock to look at the id.
* The ID can't change until it gets reclaimed, and it won't *
* be reclaimed as long as we have a ref from inode and we hold * The ID can't change until it gets reclaimed, and it won't
* the ilock. * be reclaimed as long as we have a ref from inode and we
*/ * hold the ilock.
if (udqhint && */
(dqp = udqhint->q_gdquot) && dqp = udqhint->q_gdquot;
(be32_to_cpu(dqp->q_core.d_id) == id)) { if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) {
ASSERT(XFS_DQ_IS_LOCKED(udqhint)); xfs_dqlock(dqp);
xfs_dqlock(dqp); XFS_DQHOLD(dqp);
XFS_DQHOLD(dqp); ASSERT(*IO_idqpp == NULL);
ASSERT(*IO_idqpp == NULL); *IO_idqpp = dqp;
*IO_idqpp = dqp;
if (!dolock) {
xfs_dqunlock(dqp); xfs_dqunlock(dqp);
xfs_dqunlock(udqhint); xfs_dqunlock(udqhint);
return 0;
} }
goto done;
} /*
/* * We can't hold a dquot lock when we call the dqget code.
* We can't hold a dquot lock when we call the dqget code. * We'll deadlock in no time, because of (not conforming to)
* We'll deadlock in no time, because of (not conforming to) * lock ordering - the inodelock comes before any dquot lock,
* lock ordering - the inodelock comes before any dquot lock, * and we may drop and reacquire the ilock in xfs_qm_dqget().
* and we may drop and reacquire the ilock in xfs_qm_dqget(). */
*/
if (udqhint)
xfs_dqunlock(udqhint); xfs_dqunlock(udqhint);
}
/* /*
* Find the dquot from somewhere. This bumps the * Find the dquot from somewhere. This bumps the
* reference count of dquot and returns it locked. * reference count of dquot and returns it locked.
@ -698,48 +694,19 @@ xfs_qm_dqattach_one(
* disk and we didn't ask it to allocate; * disk and we didn't ask it to allocate;
* ESRCH if quotas got turned off suddenly. * ESRCH if quotas got turned off suddenly.
*/ */
if ((error = xfs_qm_dqget(ip->i_mount, ip, id, type, error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp);
doalloc|XFS_QMOPT_DOWARN, &dqp))) { if (error)
if (udqhint && dolock) return error;
xfs_dqlock(udqhint);
goto done;
}
xfs_dqtrace_entry(dqp, "DQATTACH: found by dqget"); xfs_dqtrace_entry(dqp, "DQATTACH: found by dqget");
/* /*
* dqget may have dropped and re-acquired the ilock, but it guarantees * dqget may have dropped and re-acquired the ilock, but it guarantees
* that the dquot returned is the one that should go in the inode. * that the dquot returned is the one that should go in the inode.
*/ */
*IO_idqpp = dqp; *IO_idqpp = dqp;
ASSERT(dqp); xfs_dqunlock(dqp);
ASSERT(XFS_DQ_IS_LOCKED(dqp)); return 0;
if (! dolock) {
xfs_dqunlock(dqp);
goto done;
}
if (! udqhint)
goto done;
ASSERT(udqhint);
ASSERT(dolock);
ASSERT(XFS_DQ_IS_LOCKED(dqp));
if (! xfs_qm_dqlock_nowait(udqhint)) {
xfs_dqunlock(dqp);
xfs_dqlock(udqhint);
xfs_dqlock(dqp);
}
done:
#ifdef QUOTADEBUG
if (udqhint) {
if (dolock)
ASSERT(XFS_DQ_IS_LOCKED(udqhint));
}
if (! error) {
if (dolock)
ASSERT(XFS_DQ_IS_LOCKED(dqp));
}
#endif
return error;
} }
@ -754,24 +721,15 @@ xfs_qm_dqattach_one(
STATIC void STATIC void
xfs_qm_dqattach_grouphint( xfs_qm_dqattach_grouphint(
xfs_dquot_t *udq, xfs_dquot_t *udq,
xfs_dquot_t *gdq, xfs_dquot_t *gdq)
uint locked)
{ {
xfs_dquot_t *tmp; xfs_dquot_t *tmp;
#ifdef QUOTADEBUG xfs_dqlock(udq);
if (locked) {
ASSERT(XFS_DQ_IS_LOCKED(udq));
ASSERT(XFS_DQ_IS_LOCKED(gdq));
}
#endif
if (! locked)
xfs_dqlock(udq);
if ((tmp = udq->q_gdquot)) { if ((tmp = udq->q_gdquot)) {
if (tmp == gdq) { if (tmp == gdq) {
if (! locked) xfs_dqunlock(udq);
xfs_dqunlock(udq);
return; return;
} }
@ -781,8 +739,6 @@ xfs_qm_dqattach_grouphint(
* because the freelist lock comes before dqlocks. * because the freelist lock comes before dqlocks.
*/ */
xfs_dqunlock(udq); xfs_dqunlock(udq);
if (locked)
xfs_dqunlock(gdq);
/* /*
* we took a hard reference once upon a time in dqget, * we took a hard reference once upon a time in dqget,
* so give it back when the udquot no longer points at it * so give it back when the udquot no longer points at it
@ -795,9 +751,7 @@ xfs_qm_dqattach_grouphint(
} else { } else {
ASSERT(XFS_DQ_IS_LOCKED(udq)); ASSERT(XFS_DQ_IS_LOCKED(udq));
if (! locked) { xfs_dqlock(gdq);
xfs_dqlock(gdq);
}
} }
ASSERT(XFS_DQ_IS_LOCKED(udq)); ASSERT(XFS_DQ_IS_LOCKED(udq));
@ -810,10 +764,9 @@ xfs_qm_dqattach_grouphint(
XFS_DQHOLD(gdq); XFS_DQHOLD(gdq);
udq->q_gdquot = gdq; udq->q_gdquot = gdq;
} }
if (! locked) {
xfs_dqunlock(gdq); xfs_dqunlock(gdq);
xfs_dqunlock(udq); xfs_dqunlock(udq);
}
} }
@ -821,8 +774,6 @@ xfs_qm_dqattach_grouphint(
* Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
* into account. * into account.
* If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
* If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
* much made this code a complete mess, but it has been pretty useful.
* If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL. * If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL.
* Inode may get unlocked and relocked in here, and the caller must deal with * Inode may get unlocked and relocked in here, and the caller must deal with
* the consequences. * the consequences.
@ -851,7 +802,6 @@ xfs_qm_dqattach(
if (XFS_IS_UQUOTA_ON(mp)) { if (XFS_IS_UQUOTA_ON(mp)) {
error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER,
flags & XFS_QMOPT_DQALLOC, flags & XFS_QMOPT_DQALLOC,
flags & XFS_QMOPT_DQLOCK,
NULL, &ip->i_udquot); NULL, &ip->i_udquot);
if (error) if (error)
goto done; goto done;
@ -863,11 +813,9 @@ xfs_qm_dqattach(
error = XFS_IS_GQUOTA_ON(mp) ? error = XFS_IS_GQUOTA_ON(mp) ?
xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
flags & XFS_QMOPT_DQALLOC, flags & XFS_QMOPT_DQALLOC,
flags & XFS_QMOPT_DQLOCK,
ip->i_udquot, &ip->i_gdquot) : ip->i_udquot, &ip->i_gdquot) :
xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ, xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
flags & XFS_QMOPT_DQALLOC, flags & XFS_QMOPT_DQALLOC,
flags & XFS_QMOPT_DQLOCK,
ip->i_udquot, &ip->i_gdquot); ip->i_udquot, &ip->i_gdquot);
/* /*
* Don't worry about the udquot that we may have * Don't worry about the udquot that we may have
@ -898,22 +846,13 @@ xfs_qm_dqattach(
/* /*
* Attach i_gdquot to the gdquot hint inside the i_udquot. * Attach i_gdquot to the gdquot hint inside the i_udquot.
*/ */
xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot, xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
flags & XFS_QMOPT_DQLOCK);
} }
done: done:
#ifdef QUOTADEBUG #ifdef QUOTADEBUG
if (! error) { if (! error) {
if (ip->i_udquot) {
if (flags & XFS_QMOPT_DQLOCK)
ASSERT(XFS_DQ_IS_LOCKED(ip->i_udquot));
}
if (ip->i_gdquot) {
if (flags & XFS_QMOPT_DQLOCK)
ASSERT(XFS_DQ_IS_LOCKED(ip->i_gdquot));
}
if (XFS_IS_UQUOTA_ON(mp)) if (XFS_IS_UQUOTA_ON(mp))
ASSERT(ip->i_udquot); ASSERT(ip->i_udquot);
if (XFS_IS_OQUOTA_ON(mp)) if (XFS_IS_OQUOTA_ON(mp))
@ -2086,7 +2025,7 @@ xfs_qm_shake_freelist(
* a dqlookup process that holds the hashlock that is * a dqlookup process that holds the hashlock that is
* waiting for the freelist lock. * waiting for the freelist lock.
*/ */
if (! xfs_qm_dqhashlock_nowait(dqp)) { if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
xfs_dqfunlock(dqp); xfs_dqfunlock(dqp);
xfs_dqunlock(dqp); xfs_dqunlock(dqp);
dqp = dqp->dq_flnext; dqp = dqp->dq_flnext;
@ -2103,7 +2042,7 @@ xfs_qm_shake_freelist(
/* XXX put a sentinel so that we can come back here */ /* XXX put a sentinel so that we can come back here */
xfs_dqfunlock(dqp); xfs_dqfunlock(dqp);
xfs_dqunlock(dqp); xfs_dqunlock(dqp);
XFS_DQ_HASH_UNLOCK(hash); mutex_unlock(&hash->qh_lock);
xfs_qm_freelist_unlock(xfs_Gqm); xfs_qm_freelist_unlock(xfs_Gqm);
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
return nreclaimed; return nreclaimed;
@ -2120,7 +2059,7 @@ xfs_qm_shake_freelist(
XQM_HASHLIST_REMOVE(hash, dqp); XQM_HASHLIST_REMOVE(hash, dqp);
xfs_dqfunlock(dqp); xfs_dqfunlock(dqp);
xfs_qm_mplist_unlock(dqp->q_mount); xfs_qm_mplist_unlock(dqp->q_mount);
XFS_DQ_HASH_UNLOCK(hash); mutex_unlock(&hash->qh_lock);
off_freelist: off_freelist:
XQM_FREELIST_REMOVE(dqp); XQM_FREELIST_REMOVE(dqp);
@ -2262,7 +2201,7 @@ xfs_qm_dqreclaim_one(void)
continue; continue;
} }
if (! xfs_qm_dqhashlock_nowait(dqp)) if (!mutex_trylock(&dqp->q_hash->qh_lock))
goto mplistunlock; goto mplistunlock;
ASSERT(dqp->q_nrefs == 0); ASSERT(dqp->q_nrefs == 0);
@ -2271,7 +2210,7 @@ xfs_qm_dqreclaim_one(void)
XQM_HASHLIST_REMOVE(dqp->q_hash, dqp); XQM_HASHLIST_REMOVE(dqp->q_hash, dqp);
XQM_FREELIST_REMOVE(dqp); XQM_FREELIST_REMOVE(dqp);
dqpout = dqp; dqpout = dqp;
XFS_DQ_HASH_UNLOCK(dqp->q_hash); mutex_unlock(&dqp->q_hash->qh_lock);
mplistunlock: mplistunlock:
xfs_qm_mplist_unlock(dqp->q_mount); xfs_qm_mplist_unlock(dqp->q_mount);
xfs_dqfunlock(dqp); xfs_dqfunlock(dqp);
@ -2774,34 +2713,3 @@ xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq)
{ {
xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq); xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
} }
STATIC int
xfs_qm_dqhashlock_nowait(
xfs_dquot_t *dqp)
{
int locked;
locked = mutex_trylock(&((dqp)->q_hash->qh_lock));
return locked;
}
int
xfs_qm_freelist_lock_nowait(
xfs_qm_t *xqm)
{
int locked;
locked = mutex_trylock(&(xqm->qm_dqfreelist.qh_lock));
return locked;
}
STATIC int
xfs_qm_mplist_nowait(
xfs_mount_t *mp)
{
int locked;
ASSERT(mp->m_quotainfo);
locked = mutex_trylock(&(XFS_QI_MPLLOCK(mp)));
return locked;
}

View file

@ -27,7 +27,7 @@ struct xfs_qm;
struct xfs_inode; struct xfs_inode;
extern uint ndquot; extern uint ndquot;
extern mutex_t xfs_Gqm_lock; extern struct mutex xfs_Gqm_lock;
extern struct xfs_qm *xfs_Gqm; extern struct xfs_qm *xfs_Gqm;
extern kmem_zone_t *qm_dqzone; extern kmem_zone_t *qm_dqzone;
extern kmem_zone_t *qm_dqtrxzone; extern kmem_zone_t *qm_dqtrxzone;
@ -79,7 +79,7 @@ typedef xfs_dqhash_t xfs_dqlist_t;
typedef struct xfs_frlist { typedef struct xfs_frlist {
struct xfs_dquot *qh_next; struct xfs_dquot *qh_next;
struct xfs_dquot *qh_prev; struct xfs_dquot *qh_prev;
mutex_t qh_lock; struct mutex qh_lock;
uint qh_version; uint qh_version;
uint qh_nelems; uint qh_nelems;
} xfs_frlist_t; } xfs_frlist_t;
@ -115,7 +115,7 @@ typedef struct xfs_quotainfo {
xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */ xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */ xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */ xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
mutex_t qi_quotaofflock;/* to serialize quotaoff */ struct mutex qi_quotaofflock;/* to serialize quotaoff */
xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */ xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
uint qi_dqperchunk; /* # ondisk dqs in above chunk */ uint qi_dqperchunk; /* # ondisk dqs in above chunk */
xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */ xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
@ -158,11 +158,6 @@ typedef struct xfs_dquot_acct {
#define XFS_QM_IWARNLIMIT 5 #define XFS_QM_IWARNLIMIT 5
#define XFS_QM_RTBWARNLIMIT 5 #define XFS_QM_RTBWARNLIMIT 5
#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock))
#define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock))
#define XFS_QM_HOLD(xqm) ((xqm)->qm_nrefs++)
#define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--)
extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
extern void xfs_qm_mount_quotas(xfs_mount_t *); extern void xfs_qm_mount_quotas(xfs_mount_t *);
extern int xfs_qm_quotacheck(xfs_mount_t *); extern int xfs_qm_quotacheck(xfs_mount_t *);
@ -178,6 +173,16 @@ extern void xfs_qm_dqdetach(xfs_inode_t *);
extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint);
extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
/* quota ops */
extern int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
extern int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
fs_disk_quota_t *);
extern int xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint,
fs_disk_quota_t *);
extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint);
/* vop stuff */ /* vop stuff */
extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *, extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
uid_t, gid_t, prid_t, uint, uid_t, gid_t, prid_t, uint,
@ -194,11 +199,6 @@ extern int xfs_qm_vop_chown_reserve(xfs_trans_t *, xfs_inode_t *,
/* list stuff */ /* list stuff */
extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *); extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *);
extern void xfs_qm_freelist_unlink(xfs_dquot_t *); extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *);
/* system call interface */
extern int xfs_qm_quotactl(struct xfs_mount *, int, int,
xfs_caddr_t);
#ifdef DEBUG #ifdef DEBUG
extern int xfs_qm_internalqcheck(xfs_mount_t *); extern int xfs_qm_internalqcheck(xfs_mount_t *);

View file

@ -235,7 +235,6 @@ struct xfs_qmops xfs_qmcore_xfs = {
.xfs_dqvopchownresv = xfs_qm_vop_chown_reserve, .xfs_dqvopchownresv = xfs_qm_vop_chown_reserve,
.xfs_dqstatvfs = xfs_qm_statvfs, .xfs_dqstatvfs = xfs_qm_statvfs,
.xfs_dqsync = xfs_qm_sync, .xfs_dqsync = xfs_qm_sync,
.xfs_quotactl = xfs_qm_quotactl,
.xfs_dqtrxops = &xfs_trans_dquot_ops, .xfs_dqtrxops = &xfs_trans_dquot_ops,
}; };
EXPORT_SYMBOL(xfs_qmcore_xfs); EXPORT_SYMBOL(xfs_qmcore_xfs);

View file

@ -57,134 +57,15 @@
# define qdprintk(s, args...) do { } while (0) # define qdprintk(s, args...) do { } while (0)
#endif #endif
STATIC int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
STATIC int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
fs_disk_quota_t *);
STATIC int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
STATIC int xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint,
fs_disk_quota_t *);
STATIC int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
STATIC int xfs_qm_scall_quotaoff(xfs_mount_t *, uint, boolean_t);
STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint); STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
uint); uint);
STATIC uint xfs_qm_import_flags(uint);
STATIC uint xfs_qm_export_flags(uint); STATIC uint xfs_qm_export_flags(uint);
STATIC uint xfs_qm_import_qtype_flags(uint);
STATIC uint xfs_qm_export_qtype_flags(uint); STATIC uint xfs_qm_export_qtype_flags(uint);
STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *, STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
fs_disk_quota_t *); fs_disk_quota_t *);
/*
* The main distribution switch of all XFS quotactl system calls.
*/
int
xfs_qm_quotactl(
xfs_mount_t *mp,
int cmd,
int id,
xfs_caddr_t addr)
{
int error;
ASSERT(addr != NULL || cmd == Q_XQUOTASYNC);
/*
* The following commands are valid even when quotaoff.
*/
switch (cmd) {
case Q_XQUOTARM:
/*
* Truncate quota files. quota must be off.
*/
if (XFS_IS_QUOTA_ON(mp))
return XFS_ERROR(EINVAL);
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_trunc_qfiles(mp,
xfs_qm_import_qtype_flags(*(uint *)addr)));
case Q_XGETQSTAT:
/*
* Get quota status information.
*/
return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
case Q_XQUOTAON:
/*
* QUOTAON - enabling quota enforcement.
* Quota accounting must be turned on at mount time.
*/
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_quotaon(mp,
xfs_qm_import_flags(*(uint *)addr)));
case Q_XQUOTAOFF:
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
break;
case Q_XQUOTASYNC:
return xfs_sync_inodes(mp, SYNC_DELWRI);
default:
break;
}
if (! XFS_IS_QUOTA_ON(mp))
return XFS_ERROR(ESRCH);
switch (cmd) {
case Q_XQUOTAOFF:
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_quotaoff(mp,
xfs_qm_import_flags(*(uint *)addr),
B_FALSE);
break;
case Q_XGETQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr);
break;
case Q_XGETGQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
(fs_disk_quota_t *)addr);
break;
case Q_XGETPQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
(fs_disk_quota_t *)addr);
break;
case Q_XSETQLIM:
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr);
break;
case Q_XSETGQLIM:
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
(fs_disk_quota_t *)addr);
break;
case Q_XSETPQLIM:
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
(fs_disk_quota_t *)addr);
break;
default:
error = XFS_ERROR(EINVAL);
break;
}
return (error);
}
/* /*
* Turn off quota accounting and/or enforcement for all udquots and/or * Turn off quota accounting and/or enforcement for all udquots and/or
* gdquots. Called only at unmount time. * gdquots. Called only at unmount time.
@ -193,11 +74,10 @@ xfs_qm_quotactl(
* incore, and modifies the ondisk dquot directly. Therefore, for example, * incore, and modifies the ondisk dquot directly. Therefore, for example,
* it is an error to call this twice, without purging the cache. * it is an error to call this twice, without purging the cache.
*/ */
STATIC int int
xfs_qm_scall_quotaoff( xfs_qm_scall_quotaoff(
xfs_mount_t *mp, xfs_mount_t *mp,
uint flags, uint flags)
boolean_t force)
{ {
uint dqtype; uint dqtype;
int error; int error;
@ -205,8 +85,6 @@ xfs_qm_scall_quotaoff(
xfs_qoff_logitem_t *qoffstart; xfs_qoff_logitem_t *qoffstart;
int nculprits; int nculprits;
if (!force && !capable(CAP_SYS_ADMIN))
return XFS_ERROR(EPERM);
/* /*
* No file system can have quotas enabled on disk but not in core. * No file system can have quotas enabled on disk but not in core.
* Note that quota utilities (like quotaoff) _expect_ * Note that quota utilities (like quotaoff) _expect_
@ -375,7 +253,7 @@ xfs_qm_scall_quotaoff(
return (error); return (error);
} }
STATIC int int
xfs_qm_scall_trunc_qfiles( xfs_qm_scall_trunc_qfiles(
xfs_mount_t *mp, xfs_mount_t *mp,
uint flags) uint flags)
@ -383,8 +261,6 @@ xfs_qm_scall_trunc_qfiles(
int error = 0, error2 = 0; int error = 0, error2 = 0;
xfs_inode_t *qip; xfs_inode_t *qip;
if (!capable(CAP_SYS_ADMIN))
return XFS_ERROR(EPERM);
if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
return XFS_ERROR(EINVAL); return XFS_ERROR(EINVAL);
@ -416,7 +292,7 @@ xfs_qm_scall_trunc_qfiles(
* effect immediately. * effect immediately.
* (Switching on quota accounting must be done at mount time.) * (Switching on quota accounting must be done at mount time.)
*/ */
STATIC int int
xfs_qm_scall_quotaon( xfs_qm_scall_quotaon(
xfs_mount_t *mp, xfs_mount_t *mp,
uint flags) uint flags)
@ -426,9 +302,6 @@ xfs_qm_scall_quotaon(
uint accflags; uint accflags;
__int64_t sbflags; __int64_t sbflags;
if (!capable(CAP_SYS_ADMIN))
return XFS_ERROR(EPERM);
flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD); flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
/* /*
* Switching on quota accounting must be done at mount time. * Switching on quota accounting must be done at mount time.
@ -517,7 +390,7 @@ xfs_qm_scall_quotaon(
/* /*
* Return quota status information, such as uquota-off, enforcements, etc. * Return quota status information, such as uquota-off, enforcements, etc.
*/ */
STATIC int int
xfs_qm_scall_getqstat( xfs_qm_scall_getqstat(
xfs_mount_t *mp, xfs_mount_t *mp,
fs_quota_stat_t *out) fs_quota_stat_t *out)
@ -582,7 +455,7 @@ xfs_qm_scall_getqstat(
/* /*
* Adjust quota limits, and start/stop timers accordingly. * Adjust quota limits, and start/stop timers accordingly.
*/ */
STATIC int int
xfs_qm_scall_setqlim( xfs_qm_scall_setqlim(
xfs_mount_t *mp, xfs_mount_t *mp,
xfs_dqid_t id, xfs_dqid_t id,
@ -595,9 +468,6 @@ xfs_qm_scall_setqlim(
int error; int error;
xfs_qcnt_t hard, soft; xfs_qcnt_t hard, soft;
if (!capable(CAP_SYS_ADMIN))
return XFS_ERROR(EPERM);
if ((newlim->d_fieldmask & if ((newlim->d_fieldmask &
(FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0) (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0)
return (0); return (0);
@ -742,7 +612,7 @@ xfs_qm_scall_setqlim(
return error; return error;
} }
STATIC int int
xfs_qm_scall_getquota( xfs_qm_scall_getquota(
xfs_mount_t *mp, xfs_mount_t *mp,
xfs_dqid_t id, xfs_dqid_t id,
@ -934,30 +804,6 @@ xfs_qm_export_dquot(
#endif #endif
} }
STATIC uint
xfs_qm_import_qtype_flags(
uint uflags)
{
uint oflags = 0;
/*
* Can't be more than one, or none.
*/
if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
(XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ==
(XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ||
((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ==
(XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ||
((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0))
return (0);
oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0;
oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0;
oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0;
return oflags;
}
STATIC uint STATIC uint
xfs_qm_export_qtype_flags( xfs_qm_export_qtype_flags(
uint flags) uint flags)
@ -978,26 +824,6 @@ xfs_qm_export_qtype_flags(
XFS_PROJ_QUOTA : XFS_GROUP_QUOTA; XFS_PROJ_QUOTA : XFS_GROUP_QUOTA;
} }
STATIC uint
xfs_qm_import_flags(
uint uflags)
{
uint flags = 0;
if (uflags & XFS_QUOTA_UDQ_ACCT)
flags |= XFS_UQUOTA_ACCT;
if (uflags & XFS_QUOTA_PDQ_ACCT)
flags |= XFS_PQUOTA_ACCT;
if (uflags & XFS_QUOTA_GDQ_ACCT)
flags |= XFS_GQUOTA_ACCT;
if (uflags & XFS_QUOTA_UDQ_ENFD)
flags |= XFS_UQUOTA_ENFD;
if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
flags |= XFS_OQUOTA_ENFD;
return (flags);
}
STATIC uint STATIC uint
xfs_qm_export_flags( xfs_qm_export_flags(
uint flags) uint flags)
@ -1134,7 +960,7 @@ xfs_dqhash_t *qmtest_udqtab;
xfs_dqhash_t *qmtest_gdqtab; xfs_dqhash_t *qmtest_gdqtab;
int qmtest_hashmask; int qmtest_hashmask;
int qmtest_nfails; int qmtest_nfails;
mutex_t qcheck_lock; struct mutex qcheck_lock;
#define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \ #define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \
(__psunsigned_t)(id)) & \ (__psunsigned_t)(id)) & \

View file

@ -42,34 +42,24 @@
#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock) #define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
#define XFS_QI_MPL_LIST(mp) ((mp)->m_quotainfo->qi_dqlist) #define XFS_QI_MPL_LIST(mp) ((mp)->m_quotainfo->qi_dqlist)
#define XFS_QI_MPLLOCK(mp) ((mp)->m_quotainfo->qi_dqlist.qh_lock)
#define XFS_QI_MPLNEXT(mp) ((mp)->m_quotainfo->qi_dqlist.qh_next) #define XFS_QI_MPLNEXT(mp) ((mp)->m_quotainfo->qi_dqlist.qh_next)
#define XFS_QI_MPLNDQUOTS(mp) ((mp)->m_quotainfo->qi_dqlist.qh_nelems) #define XFS_QI_MPLNDQUOTS(mp) ((mp)->m_quotainfo->qi_dqlist.qh_nelems)
#define XQMLCK(h) (mutex_lock(&((h)->qh_lock))) #define xfs_qm_mplist_lock(mp) \
#define XQMUNLCK(h) (mutex_unlock(&((h)->qh_lock))) mutex_lock(&(XFS_QI_MPL_LIST(mp).qh_lock))
#ifdef DEBUG #define xfs_qm_mplist_nowait(mp) \
struct xfs_dqhash; mutex_trylock(&(XFS_QI_MPL_LIST(mp).qh_lock))
static inline int XQMISLCKD(struct xfs_dqhash *h) #define xfs_qm_mplist_unlock(mp) \
{ mutex_unlock(&(XFS_QI_MPL_LIST(mp).qh_lock))
if (mutex_trylock(&h->qh_lock)) { #define XFS_QM_IS_MPLIST_LOCKED(mp) \
mutex_unlock(&h->qh_lock); mutex_is_locked(&(XFS_QI_MPL_LIST(mp).qh_lock))
return 0;
}
return 1;
}
#endif
#define XFS_DQ_HASH_LOCK(h) XQMLCK(h) #define xfs_qm_freelist_lock(qm) \
#define XFS_DQ_HASH_UNLOCK(h) XQMUNLCK(h) mutex_lock(&((qm)->qm_dqfreelist.qh_lock))
#define XFS_DQ_IS_HASH_LOCKED(h) XQMISLCKD(h) #define xfs_qm_freelist_lock_nowait(qm) \
mutex_trylock(&((qm)->qm_dqfreelist.qh_lock))
#define xfs_qm_mplist_lock(mp) XQMLCK(&(XFS_QI_MPL_LIST(mp))) #define xfs_qm_freelist_unlock(qm) \
#define xfs_qm_mplist_unlock(mp) XQMUNLCK(&(XFS_QI_MPL_LIST(mp))) mutex_unlock(&((qm)->qm_dqfreelist.qh_lock))
#define XFS_QM_IS_MPLIST_LOCKED(mp) XQMISLCKD(&(XFS_QI_MPL_LIST(mp)))
#define xfs_qm_freelist_lock(qm) XQMLCK(&((qm)->qm_dqfreelist))
#define xfs_qm_freelist_unlock(qm) XQMUNLCK(&((qm)->qm_dqfreelist))
/* /*
* Hash into a bucket in the dquot hash table, based on <mp, id>. * Hash into a bucket in the dquot hash table, based on <mp, id>.

View file

@ -624,10 +624,9 @@ xfs_trans_dqresv(
xfs_qcnt_t *resbcountp; xfs_qcnt_t *resbcountp;
xfs_quotainfo_t *q = mp->m_quotainfo; xfs_quotainfo_t *q = mp->m_quotainfo;
if (! (flags & XFS_QMOPT_DQLOCK)) {
xfs_dqlock(dqp); xfs_dqlock(dqp);
}
ASSERT(XFS_DQ_IS_LOCKED(dqp));
if (flags & XFS_TRANS_DQ_RES_BLKS) { if (flags & XFS_TRANS_DQ_RES_BLKS) {
hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit); hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
if (!hardlimit) if (!hardlimit)
@ -740,10 +739,8 @@ xfs_trans_dqresv(
ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount)); ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount));
error_return: error_return:
if (! (flags & XFS_QMOPT_DQLOCK)) { xfs_dqunlock(dqp);
xfs_dqunlock(dqp); return error;
}
return (error);
} }
@ -753,8 +750,7 @@ xfs_trans_dqresv(
* grp/prj quotas is important, because this follows a both-or-nothing * grp/prj quotas is important, because this follows a both-or-nothing
* approach. * approach.
* *
* flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
* XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
* XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota.
* XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
* XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks

View file

@ -24,6 +24,7 @@
#include "xfs_ag.h" #include "xfs_ag.h"
#include "xfs_dmapi.h" #include "xfs_dmapi.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_error.h"
static char message[1024]; /* keep it off the stack */ static char message[1024]; /* keep it off the stack */
static DEFINE_SPINLOCK(xfs_err_lock); static DEFINE_SPINLOCK(xfs_err_lock);

View file

@ -17,10 +17,6 @@
*/ */
#include <xfs.h> #include <xfs.h>
static DEFINE_MUTEX(uuid_monitor);
static int uuid_table_size;
static uuid_t *uuid_table;
/* IRIX interpretation of an uuid_t */ /* IRIX interpretation of an uuid_t */
typedef struct { typedef struct {
__be32 uu_timelow; __be32 uu_timelow;
@ -46,12 +42,6 @@ uuid_getnodeuniq(uuid_t *uuid, int fsid [2])
fsid[1] = be32_to_cpu(uup->uu_timelow); fsid[1] = be32_to_cpu(uup->uu_timelow);
} }
void
uuid_create_nil(uuid_t *uuid)
{
memset(uuid, 0, sizeof(*uuid));
}
int int
uuid_is_nil(uuid_t *uuid) uuid_is_nil(uuid_t *uuid)
{ {
@ -71,64 +61,3 @@ uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
{ {
return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1; return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1;
} }
/*
* Given a 128-bit uuid, return a 64-bit value by adding the top and bottom
* 64-bit words. NOTE: This function can not be changed EVER. Although
* brain-dead, some applications depend on this 64-bit value remaining
* persistent. Specifically, DMI vendors store the value as a persistent
* filehandle.
*/
__uint64_t
uuid_hash64(uuid_t *uuid)
{
__uint64_t *sp = (__uint64_t *)uuid;
return sp[0] + sp[1];
}
int
uuid_table_insert(uuid_t *uuid)
{
int i, hole;
mutex_lock(&uuid_monitor);
for (i = 0, hole = -1; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i])) {
hole = i;
continue;
}
if (uuid_equal(uuid, &uuid_table[i])) {
mutex_unlock(&uuid_monitor);
return 0;
}
}
if (hole < 0) {
uuid_table = kmem_realloc(uuid_table,
(uuid_table_size + 1) * sizeof(*uuid_table),
uuid_table_size * sizeof(*uuid_table),
KM_SLEEP);
hole = uuid_table_size++;
}
uuid_table[hole] = *uuid;
mutex_unlock(&uuid_monitor);
return 1;
}
void
uuid_table_remove(uuid_t *uuid)
{
int i;
mutex_lock(&uuid_monitor);
for (i = 0; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i]))
continue;
if (!uuid_equal(uuid, &uuid_table[i]))
continue;
uuid_create_nil(&uuid_table[i]);
break;
}
ASSERT(i < uuid_table_size);
mutex_unlock(&uuid_monitor);
}

View file

@ -22,12 +22,8 @@ typedef struct {
unsigned char __u_bits[16]; unsigned char __u_bits[16];
} uuid_t; } uuid_t;
extern void uuid_create_nil(uuid_t *uuid);
extern int uuid_is_nil(uuid_t *uuid); extern int uuid_is_nil(uuid_t *uuid);
extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2); extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]); extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
extern __uint64_t uuid_hash64(uuid_t *uuid);
extern int uuid_table_insert(uuid_t *uuid);
extern void uuid_table_remove(uuid_t *uuid);
#endif /* __XFS_SUPPORT_UUID_H__ */ #endif /* __XFS_SUPPORT_UUID_H__ */

View file

@ -223,8 +223,8 @@ typedef struct xfs_perag
be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp)) be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp))
#define XFS_MIN_FREELIST_PAG(pag,mp) \ #define XFS_MIN_FREELIST_PAG(pag,mp) \
(XFS_MIN_FREELIST_RAW( \ (XFS_MIN_FREELIST_RAW( \
(uint_t)(pag)->pagf_levels[XFS_BTNUM_BNOi], \ (unsigned int)(pag)->pagf_levels[XFS_BTNUM_BNOi], \
(uint_t)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp)) (unsigned int)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp))
#define XFS_AGB_TO_FSB(mp,agno,agbno) \ #define XFS_AGB_TO_FSB(mp,agno,agbno) \
(((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno)) (((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno))

View file

@ -1871,6 +1871,25 @@ xfs_alloc_compute_maxlevels(
mp->m_ag_maxlevels = level; mp->m_ag_maxlevels = level;
} }
/*
* Find the length of the longest extent in an AG.
*/
xfs_extlen_t
xfs_alloc_longest_free_extent(
struct xfs_mount *mp,
struct xfs_perag *pag)
{
xfs_extlen_t need, delta = 0;
need = XFS_MIN_FREELIST_PAG(pag, mp);
if (need > pag->pagf_flcount)
delta = need - pag->pagf_flcount;
if (pag->pagf_longest > delta)
return pag->pagf_longest - delta;
return pag->pagf_flcount > 0 || pag->pagf_longest > 0;
}
/* /*
* Decide whether to use this allocation group for this allocation. * Decide whether to use this allocation group for this allocation.
* If so, fix up the btree freelist's size. * If so, fix up the btree freelist's size.
@ -1923,15 +1942,12 @@ xfs_alloc_fix_freelist(
} }
if (!(flags & XFS_ALLOC_FLAG_FREEING)) { if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
need = XFS_MIN_FREELIST_PAG(pag, mp);
delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
/* /*
* If it looks like there isn't a long enough extent, or enough * If it looks like there isn't a long enough extent, or enough
* total blocks, reject it. * total blocks, reject it.
*/ */
longest = (pag->pagf_longest > delta) ? need = XFS_MIN_FREELIST_PAG(pag, mp);
(pag->pagf_longest - delta) : longest = xfs_alloc_longest_free_extent(mp, pag);
(pag->pagf_flcount > 0 || pag->pagf_longest > 0);
if ((args->minlen + args->alignment + args->minalignslop - 1) > if ((args->minlen + args->alignment + args->minalignslop - 1) >
longest || longest ||
((int)(pag->pagf_freeblks + pag->pagf_flcount - ((int)(pag->pagf_freeblks + pag->pagf_flcount -

View file

@ -100,6 +100,12 @@ typedef struct xfs_alloc_arg {
#define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/ #define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/
#define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */ #define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */
/*
* Find the length of the longest extent in an AG.
*/
xfs_extlen_t
xfs_alloc_longest_free_extent(struct xfs_mount *mp,
struct xfs_perag *pag);
#ifdef __KERNEL__ #ifdef __KERNEL__

View file

@ -155,7 +155,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
* minimum offset only needs to be the space required for * minimum offset only needs to be the space required for
* the btree root. * the btree root.
*/ */
if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset) if (!dp->i_d.di_forkoff && dp->i_df.if_bytes >
xfs_default_attroffset(dp))
dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
break; break;
@ -297,6 +298,26 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
xfs_sbversion_add_attr2(mp, args->trans); xfs_sbversion_add_attr2(mp, args->trans);
} }
/*
* After the last attribute is removed revert to original inode format,
* making all literal area available to the data fork once more.
*/
STATIC void
xfs_attr_fork_reset(
struct xfs_inode *ip,
struct xfs_trans *tp)
{
xfs_idestroy_fork(ip, XFS_ATTR_FORK);
ip->i_d.di_forkoff = 0;
ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
ASSERT(ip->i_d.di_anextents == 0);
ASSERT(ip->i_afp == NULL);
ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
}
/* /*
* Remove an attribute from the shortform attribute list structure. * Remove an attribute from the shortform attribute list structure.
*/ */
@ -344,22 +365,10 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
*/ */
totsize -= size; totsize -= size;
if (totsize == sizeof(xfs_attr_sf_hdr_t) && if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
!(args->op_flags & XFS_DA_OP_ADDNAME) && (mp->m_flags & XFS_MOUNT_ATTR2) &&
(mp->m_flags & XFS_MOUNT_ATTR2) && (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
(dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) { !(args->op_flags & XFS_DA_OP_ADDNAME)) {
/* xfs_attr_fork_reset(dp, args->trans);
* Last attribute now removed, revert to original
* inode format making all literal area available
* to the data fork once more.
*/
xfs_idestroy_fork(dp, XFS_ATTR_FORK);
dp->i_d.di_forkoff = 0;
dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
ASSERT(dp->i_d.di_anextents == 0);
ASSERT(dp->i_afp == NULL);
dp->i_df.if_ext_max =
XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
} else { } else {
xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
@ -786,20 +795,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
if (forkoff == -1) { if (forkoff == -1) {
ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
xfs_attr_fork_reset(dp, args->trans);
/*
* Last attribute was removed, revert to original
* inode format making all literal area available
* to the data fork once more.
*/
xfs_idestroy_fork(dp, XFS_ATTR_FORK);
dp->i_d.di_forkoff = 0;
dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
ASSERT(dp->i_d.di_anextents == 0);
ASSERT(dp->i_afp == NULL);
dp->i_df.if_ext_max =
XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
goto out; goto out;
} }

View file

@ -2479,7 +2479,7 @@ xfs_bmap_adjacent(
fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
/* /*
* If allocating at eof, and there's a previous real block, * If allocating at eof, and there's a previous real block,
* try to use it's last block as our starting point. * try to use its last block as our starting point.
*/ */
if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF && if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF &&
!isnullstartblock(ap->prevp->br_startblock) && !isnullstartblock(ap->prevp->br_startblock) &&
@ -2712,9 +2712,6 @@ xfs_bmap_btalloc(
xfs_agnumber_t startag; xfs_agnumber_t startag;
xfs_alloc_arg_t args; xfs_alloc_arg_t args;
xfs_extlen_t blen; xfs_extlen_t blen;
xfs_extlen_t delta;
xfs_extlen_t longest;
xfs_extlen_t need;
xfs_extlen_t nextminlen = 0; xfs_extlen_t nextminlen = 0;
xfs_perag_t *pag; xfs_perag_t *pag;
int nullfb; /* true if ap->firstblock isn't set */ int nullfb; /* true if ap->firstblock isn't set */
@ -2796,13 +2793,8 @@ xfs_bmap_btalloc(
* See xfs_alloc_fix_freelist... * See xfs_alloc_fix_freelist...
*/ */
if (pag->pagf_init) { if (pag->pagf_init) {
need = XFS_MIN_FREELIST_PAG(pag, mp); xfs_extlen_t longest;
delta = need > pag->pagf_flcount ? longest = xfs_alloc_longest_free_extent(mp, pag);
need - pag->pagf_flcount : 0;
longest = (pag->pagf_longest > delta) ?
(pag->pagf_longest - delta) :
(pag->pagf_flcount > 0 ||
pag->pagf_longest > 0);
if (blen < longest) if (blen < longest)
blen = longest; blen = longest;
} else } else
@ -3576,6 +3568,27 @@ xfs_bmap_extents_to_btree(
return 0; return 0;
} }
/*
* Calculate the default attribute fork offset for newly created inodes.
*/
uint
xfs_default_attroffset(
struct xfs_inode *ip)
{
struct xfs_mount *mp = ip->i_mount;
uint offset;
if (mp->m_sb.sb_inodesize == 256) {
offset = XFS_LITINO(mp) -
XFS_BMDR_SPACE_CALC(MINABTPTRS);
} else {
offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
}
ASSERT(offset < XFS_LITINO(mp));
return offset;
}
/* /*
* Helper routine to reset inode di_forkoff field when switching * Helper routine to reset inode di_forkoff field when switching
* attribute fork from local to extent format - we reset it where * attribute fork from local to extent format - we reset it where
@ -3588,15 +3601,18 @@ xfs_bmap_forkoff_reset(
int whichfork) int whichfork)
{ {
if (whichfork == XFS_ATTR_FORK && if (whichfork == XFS_ATTR_FORK &&
(ip->i_d.di_format != XFS_DINODE_FMT_DEV) && ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
(ip->i_d.di_format != XFS_DINODE_FMT_UUID) && ip->i_d.di_format != XFS_DINODE_FMT_UUID &&
(ip->i_d.di_format != XFS_DINODE_FMT_BTREE) && ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) { uint dfl_forkoff = xfs_default_attroffset(ip) >> 3;
ip->i_d.di_forkoff = mp->m_attroffset >> 3;
ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / if (dfl_forkoff > ip->i_d.di_forkoff) {
(uint)sizeof(xfs_bmbt_rec_t); ip->i_d.di_forkoff = dfl_forkoff;
ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) / ip->i_df.if_ext_max =
(uint)sizeof(xfs_bmbt_rec_t); XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t);
ip->i_afp->if_ext_max =
XFS_IFORK_ASIZE(ip) / sizeof(xfs_bmbt_rec_t);
}
} }
} }
@ -4065,7 +4081,7 @@ xfs_bmap_add_attrfork(
case XFS_DINODE_FMT_BTREE: case XFS_DINODE_FMT_BTREE:
ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size); ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
if (!ip->i_d.di_forkoff) if (!ip->i_d.di_forkoff)
ip->i_d.di_forkoff = mp->m_attroffset >> 3; ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
else if (mp->m_flags & XFS_MOUNT_ATTR2) else if (mp->m_flags & XFS_MOUNT_ATTR2)
version = 2; version = 2;
break; break;
@ -4212,12 +4228,12 @@ xfs_bmap_compute_maxlevels(
* (a signed 16-bit number, xfs_aextnum_t). * (a signed 16-bit number, xfs_aextnum_t).
* *
* Note that we can no longer assume that if we are in ATTR1 that * Note that we can no longer assume that if we are in ATTR1 that
* the fork offset of all the inodes will be (m_attroffset >> 3) * the fork offset of all the inodes will be
* because we could have mounted with ATTR2 and then mounted back * (xfs_default_attroffset(ip) >> 3) because we could have mounted
* with ATTR1, keeping the di_forkoff's fixed but probably at * with ATTR2 and then mounted back with ATTR1, keeping the
* various positions. Therefore, for both ATTR1 and ATTR2 * di_forkoff's fixed but probably at various positions. Therefore,
* we have to assume the worst case scenario of a minimum size * for both ATTR1 and ATTR2 we have to assume the worst case scenario
* available. * of a minimum size available.
*/ */
if (whichfork == XFS_DATA_FORK) { if (whichfork == XFS_DATA_FORK) {
maxleafents = MAXEXTNUM; maxleafents = MAXEXTNUM;
@ -4804,7 +4820,7 @@ xfs_bmapi(
xfs_extlen_t minlen; /* min allocation size */ xfs_extlen_t minlen; /* min allocation size */
xfs_mount_t *mp; /* xfs mount structure */ xfs_mount_t *mp; /* xfs mount structure */
int n; /* current extent index */ int n; /* current extent index */
int nallocs; /* number of extents alloc\'d */ int nallocs; /* number of extents alloc'd */
xfs_extnum_t nextents; /* number of extents in file */ xfs_extnum_t nextents; /* number of extents in file */
xfs_fileoff_t obno; /* old block number (offset) */ xfs_fileoff_t obno; /* old block number (offset) */
xfs_bmbt_irec_t prev; /* previous file extent record */ xfs_bmbt_irec_t prev; /* previous file extent record */
@ -6204,7 +6220,7 @@ xfs_bmap_get_bp(
return(bp); return(bp);
} }
void STATIC void
xfs_check_block( xfs_check_block(
struct xfs_btree_block *block, struct xfs_btree_block *block,
xfs_mount_t *mp, xfs_mount_t *mp,
@ -6494,7 +6510,7 @@ xfs_bmap_count_tree(
block = XFS_BUF_TO_BLOCK(bp); block = XFS_BUF_TO_BLOCK(bp);
if (--level) { if (--level) {
/* Not at node above leafs, count this level of nodes */ /* Not at node above leaves, count this level of nodes */
nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
while (nextbno != NULLFSBLOCK) { while (nextbno != NULLFSBLOCK) {
if ((error = xfs_btree_read_bufl(mp, tp, nextbno, if ((error = xfs_btree_read_bufl(mp, tp, nextbno,

View file

@ -125,7 +125,7 @@ typedef struct xfs_bmalloca {
struct xfs_bmbt_irec *gotp; /* extent after, or delayed */ struct xfs_bmbt_irec *gotp; /* extent after, or delayed */
xfs_extlen_t alen; /* i/o length asked/allocated */ xfs_extlen_t alen; /* i/o length asked/allocated */
xfs_extlen_t total; /* total blocks needed for xaction */ xfs_extlen_t total; /* total blocks needed for xaction */
xfs_extlen_t minlen; /* mininum allocation size (blocks) */ xfs_extlen_t minlen; /* minimum allocation size (blocks) */
xfs_extlen_t minleft; /* amount must be left after alloc */ xfs_extlen_t minleft; /* amount must be left after alloc */
char eof; /* set if allocating past last extent */ char eof; /* set if allocating past last extent */
char wasdel; /* replacing a delayed allocation */ char wasdel; /* replacing a delayed allocation */
@ -338,6 +338,10 @@ xfs_check_nostate_extents(
xfs_extnum_t idx, xfs_extnum_t idx,
xfs_extnum_t num); xfs_extnum_t num);
uint
xfs_default_attroffset(
struct xfs_inode *ip);
#ifdef __KERNEL__ #ifdef __KERNEL__
/* /*

View file

@ -1883,7 +1883,7 @@ xfs_btree_lshift(
/* /*
* We add one entry to the left side and remove one for the right side. * We add one entry to the left side and remove one for the right side.
* Accout for it here, the changes will be updated on disk and logged * Account for it here, the changes will be updated on disk and logged
* later. * later.
*/ */
lrecs++; lrecs++;
@ -3535,7 +3535,7 @@ xfs_btree_delrec(
XFS_BTREE_STATS_INC(cur, join); XFS_BTREE_STATS_INC(cur, join);
/* /*
* Fix up the the number of records and right block pointer in the * Fix up the number of records and right block pointer in the
* surviving block, and log it. * surviving block, and log it.
*/ */
xfs_btree_set_numrecs(left, lrecs + rrecs); xfs_btree_set_numrecs(left, lrecs + rrecs);

View file

@ -41,7 +41,7 @@ extern kmem_zone_t *xfs_btree_cur_zone;
/* /*
* Generic btree header. * Generic btree header.
* *
* This is a comination of the actual format used on disk for short and long * This is a combination of the actual format used on disk for short and long
* format btrees. The first three fields are shared by both format, but * format btrees. The first three fields are shared by both format, but
* the pointers are different and should be used with care. * the pointers are different and should be used with care.
* *

View file

@ -1503,7 +1503,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
* This is implemented with some source-level loop unrolling. * This is implemented with some source-level loop unrolling.
*/ */
xfs_dahash_t xfs_dahash_t
xfs_da_hashname(const uchar_t *name, int namelen) xfs_da_hashname(const __uint8_t *name, int namelen)
{ {
xfs_dahash_t hash; xfs_dahash_t hash;

View file

@ -91,9 +91,9 @@ enum xfs_dacmp {
* Structure to ease passing around component names. * Structure to ease passing around component names.
*/ */
typedef struct xfs_da_args { typedef struct xfs_da_args {
const uchar_t *name; /* string (maybe not NULL terminated) */ const __uint8_t *name; /* string (maybe not NULL terminated) */
int namelen; /* length of string (maybe no NULL) */ int namelen; /* length of string (maybe no NULL) */
uchar_t *value; /* set of bytes (maybe contain NULLs) */ __uint8_t *value; /* set of bytes (maybe contain NULLs) */
int valuelen; /* length of value */ int valuelen; /* length of value */
int flags; /* argument flags (eg: ATTR_NOCREATE) */ int flags; /* argument flags (eg: ATTR_NOCREATE) */
xfs_dahash_t hashval; /* hash value of name */ xfs_dahash_t hashval; /* hash value of name */
@ -185,7 +185,7 @@ typedef struct xfs_da_state {
unsigned char inleaf; /* insert into 1->lf, 0->splf */ unsigned char inleaf; /* insert into 1->lf, 0->splf */
unsigned char extravalid; /* T/F: extrablk is in use */ unsigned char extravalid; /* T/F: extrablk is in use */
unsigned char extraafter; /* T/F: extrablk is after new */ unsigned char extraafter; /* T/F: extrablk is after new */
xfs_da_state_blk_t extrablk; /* for double-splits on leafs */ xfs_da_state_blk_t extrablk; /* for double-splits on leaves */
/* for dirv2 extrablk is data */ /* for dirv2 extrablk is data */
} xfs_da_state_t; } xfs_da_state_t;
@ -251,7 +251,7 @@ xfs_daddr_t xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp,
int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
xfs_dabuf_t *dead_buf); xfs_dabuf_t *dead_buf);
uint xfs_da_hashname(const uchar_t *name_string, int name_length); uint xfs_da_hashname(const __uint8_t *name_string, int name_length);
enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args,
const char *name, int len); const char *name, int len);
@ -268,5 +268,6 @@ xfs_daddr_t xfs_da_blkno(xfs_dabuf_t *dabuf);
extern struct kmem_zone *xfs_da_state_zone; extern struct kmem_zone *xfs_da_state_zone;
extern struct kmem_zone *xfs_dabuf_zone; extern struct kmem_zone *xfs_dabuf_zone;
extern const struct xfs_nameops xfs_default_nameops;
#endif /* __XFS_DA_BTREE_H__ */ #endif /* __XFS_DA_BTREE_H__ */

View file

@ -79,6 +79,12 @@ xfs_swapext(
goto out_put_target_file; goto out_put_target_file;
} }
if (IS_SWAPFILE(file->f_path.dentry->d_inode) ||
IS_SWAPFILE(target_file->f_path.dentry->d_inode)) {
error = XFS_ERROR(EINVAL);
goto out_put_target_file;
}
ip = XFS_I(file->f_path.dentry->d_inode); ip = XFS_I(file->f_path.dentry->d_inode);
tip = XFS_I(target_file->f_path.dentry->d_inode); tip = XFS_I(target_file->f_path.dentry->d_inode);
@ -118,19 +124,17 @@ xfs_swap_extents(
xfs_bstat_t *sbp = &sxp->sx_stat; xfs_bstat_t *sbp = &sxp->sx_stat;
xfs_ifork_t *tempifp, *ifp, *tifp; xfs_ifork_t *tempifp, *ifp, *tifp;
int ilf_fields, tilf_fields; int ilf_fields, tilf_fields;
static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
int error = 0; int error = 0;
int aforkblks = 0; int aforkblks = 0;
int taforkblks = 0; int taforkblks = 0;
__uint64_t tmp; __uint64_t tmp;
char locked = 0;
mp = ip->i_mount; mp = ip->i_mount;
tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
if (!tempifp) { if (!tempifp) {
error = XFS_ERROR(ENOMEM); error = XFS_ERROR(ENOMEM);
goto error0; goto out;
} }
sbp = &sxp->sx_stat; sbp = &sxp->sx_stat;
@ -143,25 +147,24 @@ xfs_swap_extents(
*/ */
xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL);
xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
locked = 1;
/* Verify that both files have the same format */ /* Verify that both files have the same format */
if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) { if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
error = XFS_ERROR(EINVAL); error = XFS_ERROR(EINVAL);
goto error0; goto out_unlock;
} }
/* Verify both files are either real-time or non-realtime */ /* Verify both files are either real-time or non-realtime */
if (XFS_IS_REALTIME_INODE(ip) != XFS_IS_REALTIME_INODE(tip)) { if (XFS_IS_REALTIME_INODE(ip) != XFS_IS_REALTIME_INODE(tip)) {
error = XFS_ERROR(EINVAL); error = XFS_ERROR(EINVAL);
goto error0; goto out_unlock;
} }
/* Should never get a local format */ /* Should never get a local format */
if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL || if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) { tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
error = XFS_ERROR(EINVAL); error = XFS_ERROR(EINVAL);
goto error0; goto out_unlock;
} }
if (VN_CACHED(VFS_I(tip)) != 0) { if (VN_CACHED(VFS_I(tip)) != 0) {
@ -169,13 +172,13 @@ xfs_swap_extents(
error = xfs_flushinval_pages(tip, 0, -1, error = xfs_flushinval_pages(tip, 0, -1,
FI_REMAPF_LOCKED); FI_REMAPF_LOCKED);
if (error) if (error)
goto error0; goto out_unlock;
} }
/* Verify O_DIRECT for ftmp */ /* Verify O_DIRECT for ftmp */
if (VN_CACHED(VFS_I(tip)) != 0) { if (VN_CACHED(VFS_I(tip)) != 0) {
error = XFS_ERROR(EINVAL); error = XFS_ERROR(EINVAL);
goto error0; goto out_unlock;
} }
/* Verify all data are being swapped */ /* Verify all data are being swapped */
@ -183,7 +186,7 @@ xfs_swap_extents(
sxp->sx_length != ip->i_d.di_size || sxp->sx_length != ip->i_d.di_size ||
sxp->sx_length != tip->i_d.di_size) { sxp->sx_length != tip->i_d.di_size) {
error = XFS_ERROR(EFAULT); error = XFS_ERROR(EFAULT);
goto error0; goto out_unlock;
} }
/* /*
@ -193,7 +196,7 @@ xfs_swap_extents(
*/ */
if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) { if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) {
error = XFS_ERROR(EINVAL); error = XFS_ERROR(EINVAL);
goto error0; goto out_unlock;
} }
/* /*
@ -208,7 +211,7 @@ xfs_swap_extents(
(sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) || (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) ||
(sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) { (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) {
error = XFS_ERROR(EBUSY); error = XFS_ERROR(EBUSY);
goto error0; goto out_unlock;
} }
/* We need to fail if the file is memory mapped. Once we have tossed /* We need to fail if the file is memory mapped. Once we have tossed
@ -219,7 +222,7 @@ xfs_swap_extents(
*/ */
if (VN_MAPPED(VFS_I(ip))) { if (VN_MAPPED(VFS_I(ip))) {
error = XFS_ERROR(EBUSY); error = XFS_ERROR(EBUSY);
goto error0; goto out_unlock;
} }
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
@ -242,8 +245,7 @@ xfs_swap_extents(
xfs_iunlock(ip, XFS_IOLOCK_EXCL); xfs_iunlock(ip, XFS_IOLOCK_EXCL);
xfs_iunlock(tip, XFS_IOLOCK_EXCL); xfs_iunlock(tip, XFS_IOLOCK_EXCL);
xfs_trans_cancel(tp, 0); xfs_trans_cancel(tp, 0);
locked = 0; goto out;
goto error0;
} }
xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
@ -253,19 +255,15 @@ xfs_swap_extents(
if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) && if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks); error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks);
if (error) { if (error)
xfs_trans_cancel(tp, 0); goto out_trans_cancel;
goto error0;
}
} }
if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) && if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
(tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK,
&taforkblks); &taforkblks);
if (error) { if (error)
xfs_trans_cancel(tp, 0); goto out_trans_cancel;
goto error0;
}
} }
/* /*
@ -332,10 +330,10 @@ xfs_swap_extents(
IHOLD(ip); IHOLD(ip);
xfs_trans_ijoin(tp, ip, lock_flags); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
IHOLD(tip); IHOLD(tip);
xfs_trans_ijoin(tp, tip, lock_flags); xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
xfs_trans_log_inode(tp, ip, ilf_fields); xfs_trans_log_inode(tp, ip, ilf_fields);
xfs_trans_log_inode(tp, tip, tilf_fields); xfs_trans_log_inode(tp, tip, tilf_fields);
@ -344,19 +342,19 @@ xfs_swap_extents(
* If this is a synchronous mount, make sure that the * If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user. * transaction goes to disk before returning to the user.
*/ */
if (mp->m_flags & XFS_MOUNT_WSYNC) { if (mp->m_flags & XFS_MOUNT_WSYNC)
xfs_trans_set_sync(tp); xfs_trans_set_sync(tp);
}
error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT); error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT);
locked = 0;
error0: out_unlock:
if (locked) { xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
xfs_iunlock(ip, lock_flags); xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
xfs_iunlock(tip, lock_flags); out:
} kmem_free(tempifp);
if (tempifp != NULL)
kmem_free(tempifp);
return error; return error;
out_trans_cancel:
xfs_trans_cancel(tp, 0);
goto out_unlock;
} }

View file

@ -103,7 +103,9 @@ typedef enum xfs_dinode_fmt {
/* /*
* Inode size for given fs. * Inode size for given fs.
*/ */
#define XFS_LITINO(mp) ((mp)->m_litino) #define XFS_LITINO(mp) \
((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
#define XFS_BROOT_SIZE_ADJ \ #define XFS_BROOT_SIZE_ADJ \
(XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t)) (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t))

View file

@ -46,8 +46,6 @@
struct xfs_name xfs_name_dotdot = {"..", 2}; struct xfs_name xfs_name_dotdot = {"..", 2};
extern const struct xfs_nameops xfs_default_nameops;
/* /*
* ASCII case-insensitive (ie. A-Z) support for directories that was * ASCII case-insensitive (ie. A-Z) support for directories that was
* used in IRIX. * used in IRIX.

View file

@ -448,7 +448,6 @@ xfs_dir2_block_getdents(
xfs_mount_t *mp; /* filesystem mount point */ xfs_mount_t *mp; /* filesystem mount point */
char *ptr; /* current data entry */ char *ptr; /* current data entry */
int wantoff; /* starting block offset */ int wantoff; /* starting block offset */
xfs_ino_t ino;
xfs_off_t cook; xfs_off_t cook;
mp = dp->i_mount; mp = dp->i_mount;
@ -509,16 +508,12 @@ xfs_dir2_block_getdents(
cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
(char *)dep - (char *)block); (char *)dep - (char *)block);
ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
/* /*
* If it didn't fit, set the final offset to here & return. * If it didn't fit, set the final offset to here & return.
*/ */
if (filldir(dirent, dep->name, dep->namelen, cook & 0x7fffffff, if (filldir(dirent, dep->name, dep->namelen, cook & 0x7fffffff,
ino, DT_UNKNOWN)) { be64_to_cpu(dep->inumber), DT_UNKNOWN)) {
*offset = cook & 0x7fffffff; *offset = cook & 0x7fffffff;
xfs_da_brelse(NULL, bp); xfs_da_brelse(NULL, bp);
return 0; return 0;

View file

@ -38,7 +38,7 @@ struct xfs_trans;
/* /*
* Directory address space divided into sections, * Directory address space divided into sections,
* spaces separated by 32gb. * spaces separated by 32GB.
*/ */
#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) #define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
#define XFS_DIR2_DATA_SPACE 0 #define XFS_DIR2_DATA_SPACE 0

View file

@ -549,7 +549,7 @@ xfs_dir2_leaf_addname(
* Check the internal consistency of a leaf1 block. * Check the internal consistency of a leaf1 block.
* Pop an assert if something is wrong. * Pop an assert if something is wrong.
*/ */
void STATIC void
xfs_dir2_leaf_check( xfs_dir2_leaf_check(
xfs_inode_t *dp, /* incore directory inode */ xfs_inode_t *dp, /* incore directory inode */
xfs_dabuf_t *bp) /* leaf's buffer */ xfs_dabuf_t *bp) /* leaf's buffer */
@ -780,7 +780,6 @@ xfs_dir2_leaf_getdents(
int ra_index; /* *map index for read-ahead */ int ra_index; /* *map index for read-ahead */
int ra_offset; /* map entry offset for ra */ int ra_offset; /* map entry offset for ra */
int ra_want; /* readahead count wanted */ int ra_want; /* readahead count wanted */
xfs_ino_t ino;
/* /*
* If the offset is at or past the largest allowed value, * If the offset is at or past the largest allowed value,
@ -1076,24 +1075,12 @@ xfs_dir2_leaf_getdents(
continue; continue;
} }
/*
* Copy the entry into the putargs, and try formatting it.
*/
dep = (xfs_dir2_data_entry_t *)ptr; dep = (xfs_dir2_data_entry_t *)ptr;
length = xfs_dir2_data_entsize(dep->namelen); length = xfs_dir2_data_entsize(dep->namelen);
ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
/*
* Won't fit. Return to caller.
*/
if (filldir(dirent, dep->name, dep->namelen, if (filldir(dirent, dep->name, dep->namelen,
xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff, xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff,
ino, DT_UNKNOWN)) be64_to_cpu(dep->inumber), DT_UNKNOWN))
break; break;
/* /*

View file

@ -1104,7 +1104,7 @@ xfs_dir2_leafn_remove(
} }
xfs_dir2_leafn_check(dp, bp); xfs_dir2_leafn_check(dp, bp);
/* /*
* Return indication of whether this leaf block is emtpy enough * Return indication of whether this leaf block is empty enough
* to justify trying to join it with a neighbor. * to justify trying to join it with a neighbor.
*/ */
*rval = *rval =

View file

@ -748,11 +748,7 @@ xfs_dir2_sf_getdents(
* Put . entry unless we're starting past it. * Put . entry unless we're starting past it.
*/ */
if (*offset <= dot_offset) { if (*offset <= dot_offset) {
ino = dp->i_ino; if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, dp->i_ino, DT_DIR)) {
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, ino, DT_DIR)) {
*offset = dot_offset & 0x7fffffff; *offset = dot_offset & 0x7fffffff;
return 0; return 0;
} }
@ -763,9 +759,6 @@ xfs_dir2_sf_getdents(
*/ */
if (*offset <= dotdot_offset) { if (*offset <= dotdot_offset) {
ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) { if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) {
*offset = dotdot_offset & 0x7fffffff; *offset = dotdot_offset & 0x7fffffff;
return 0; return 0;
@ -786,10 +779,6 @@ xfs_dir2_sf_getdents(
} }
ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep)); ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
if (filldir(dirent, sfep->name, sfep->namelen, if (filldir(dirent, sfep->name, sfep->namelen,
off & 0x7fffffff, ino, DT_UNKNOWN)) { off & 0x7fffffff, ino, DT_UNKNOWN)) {
*offset = off & 0x7fffffff; *offset = off & 0x7fffffff;

View file

@ -33,12 +33,10 @@ typedef struct xfs_extent {
* conversion routine. * conversion routine.
*/ */
#ifndef HAVE_FORMAT32
typedef struct xfs_extent_32 { typedef struct xfs_extent_32 {
__uint64_t ext_start; __uint64_t ext_start;
__uint32_t ext_len; __uint32_t ext_len;
} __attribute__((packed)) xfs_extent_32_t; } __attribute__((packed)) xfs_extent_32_t;
#endif
typedef struct xfs_extent_64 { typedef struct xfs_extent_64 {
__uint64_t ext_start; __uint64_t ext_start;
@ -59,7 +57,6 @@ typedef struct xfs_efi_log_format {
xfs_extent_t efi_extents[1]; /* array of extents to free */ xfs_extent_t efi_extents[1]; /* array of extents to free */
} xfs_efi_log_format_t; } xfs_efi_log_format_t;
#ifndef HAVE_FORMAT32
typedef struct xfs_efi_log_format_32 { typedef struct xfs_efi_log_format_32 {
__uint16_t efi_type; /* efi log item type */ __uint16_t efi_type; /* efi log item type */
__uint16_t efi_size; /* size of this item */ __uint16_t efi_size; /* size of this item */
@ -67,7 +64,6 @@ typedef struct xfs_efi_log_format_32 {
__uint64_t efi_id; /* efi identifier */ __uint64_t efi_id; /* efi identifier */
xfs_extent_32_t efi_extents[1]; /* array of extents to free */ xfs_extent_32_t efi_extents[1]; /* array of extents to free */
} __attribute__((packed)) xfs_efi_log_format_32_t; } __attribute__((packed)) xfs_efi_log_format_32_t;
#endif
typedef struct xfs_efi_log_format_64 { typedef struct xfs_efi_log_format_64 {
__uint16_t efi_type; /* efi log item type */ __uint16_t efi_type; /* efi log item type */
@ -90,7 +86,6 @@ typedef struct xfs_efd_log_format {
xfs_extent_t efd_extents[1]; /* array of extents freed */ xfs_extent_t efd_extents[1]; /* array of extents freed */
} xfs_efd_log_format_t; } xfs_efd_log_format_t;
#ifndef HAVE_FORMAT32
typedef struct xfs_efd_log_format_32 { typedef struct xfs_efd_log_format_32 {
__uint16_t efd_type; /* efd log item type */ __uint16_t efd_type; /* efd log item type */
__uint16_t efd_size; /* size of this item */ __uint16_t efd_size; /* size of this item */
@ -98,7 +93,6 @@ typedef struct xfs_efd_log_format_32 {
__uint64_t efd_efi_id; /* id of corresponding efi */ __uint64_t efd_efi_id; /* id of corresponding efi */
xfs_extent_32_t efd_extents[1]; /* array of extents freed */ xfs_extent_32_t efd_extents[1]; /* array of extents freed */
} __attribute__((packed)) xfs_efd_log_format_32_t; } __attribute__((packed)) xfs_efd_log_format_32_t;
#endif
typedef struct xfs_efd_log_format_64 { typedef struct xfs_efd_log_format_64 {
__uint16_t efd_type; /* efd log item type */ __uint16_t efd_type; /* efd log item type */

View file

@ -140,7 +140,7 @@ _xfs_filestream_pick_ag(
xfs_extlen_t minlen) xfs_extlen_t minlen)
{ {
int err, trylock, nscan; int err, trylock, nscan;
xfs_extlen_t delta, longest, need, free, minfree, maxfree = 0; xfs_extlen_t longest, free, minfree, maxfree = 0;
xfs_agnumber_t ag, max_ag = NULLAGNUMBER; xfs_agnumber_t ag, max_ag = NULLAGNUMBER;
struct xfs_perag *pag; struct xfs_perag *pag;
@ -186,12 +186,7 @@ _xfs_filestream_pick_ag(
goto next_ag; goto next_ag;
} }
need = XFS_MIN_FREELIST_PAG(pag, mp); longest = xfs_alloc_longest_free_extent(mp, pag);
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) || if (((minlen && longest >= minlen) ||
(!minlen && pag->pagf_freeblks >= minfree)) && (!minlen && pag->pagf_freeblks >= minfree)) &&
(!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) || (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) ||

View file

@ -576,7 +576,7 @@ xfs_reserve_blocks(
if (fdblks_delta) { if (fdblks_delta) {
/* /*
* If we are putting blocks back here, m_resblks_avail is * If we are putting blocks back here, m_resblks_avail is
* already at it's max so this will put it in the free pool. * already at its max so this will put it in the free pool.
* *
* If we need space, we'll either succeed in getting it * If we need space, we'll either succeed in getting it
* from the free block count or we'll get an enospc. If * from the free block count or we'll get an enospc. If

View file

@ -230,7 +230,7 @@ xfs_ialloc_ag_alloc(
args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1; args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1;
/* Allow space for the inode btree to split. */ /* Allow space for the inode btree to split. */
args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; args.minleft = args.mp->m_in_maxlevels - 1;
if ((error = xfs_alloc_vextent(&args))) if ((error = xfs_alloc_vextent(&args)))
return error; return error;
} else } else
@ -270,7 +270,7 @@ xfs_ialloc_ag_alloc(
/* /*
* Allow space for the inode btree to split. * Allow space for the inode btree to split.
*/ */
args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; args.minleft = args.mp->m_in_maxlevels - 1;
if ((error = xfs_alloc_vextent(&args))) if ((error = xfs_alloc_vextent(&args)))
return error; return error;
} }
@ -349,7 +349,7 @@ xfs_ialloc_ag_alloc(
* Initialize all inodes in this buffer and then log them. * Initialize all inodes in this buffer and then log them.
* *
* XXX: It would be much better if we had just one transaction to * XXX: It would be much better if we had just one transaction to
* log a whole cluster of inodes instead of all the indivdual * log a whole cluster of inodes instead of all the individual
* transactions causing a lot of log traffic. * transactions causing a lot of log traffic.
*/ */
xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog); xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog);
@ -943,7 +943,7 @@ xfs_dialloc(
ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) % ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
XFS_INODES_PER_CHUNK) == 0); XFS_INODES_PER_CHUNK) == 0);
ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
XFS_INOBT_CLR_FREE(&rec, offset); rec.ir_free &= ~XFS_INOBT_MASK(offset);
rec.ir_freecount--; rec.ir_freecount--;
if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount,
rec.ir_free))) rec.ir_free)))
@ -1105,11 +1105,11 @@ xfs_difree(
*/ */
off = agino - rec.ir_startino; off = agino - rec.ir_startino;
ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK); ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK);
ASSERT(!XFS_INOBT_IS_FREE(&rec, off)); ASSERT(!(rec.ir_free & XFS_INOBT_MASK(off)));
/* /*
* Mark the inode free & increment the count. * Mark the inode free & increment the count.
*/ */
XFS_INOBT_SET_FREE(&rec, off); rec.ir_free |= XFS_INOBT_MASK(off);
rec.ir_freecount++; rec.ir_freecount++;
/* /*

View file

@ -164,7 +164,7 @@ xfs_inobt_init_rec_from_cur(
} }
/* /*
* intial value of ptr for lookup * initial value of ptr for lookup
*/ */
STATIC void STATIC void
xfs_inobt_init_ptr_from_cur( xfs_inobt_init_ptr_from_cur(

View file

@ -32,14 +32,14 @@ struct xfs_mount;
#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ #define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */
typedef __uint64_t xfs_inofree_t; typedef __uint64_t xfs_inofree_t;
#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) #define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t))
#define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3) #define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3)
#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1)
#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i))
static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
{ {
return (((n) >= XFS_INODES_PER_CHUNK ? \ return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i;
(xfs_inofree_t)0 : ((xfs_inofree_t)1 << (n))) - 1) << (i);
} }
/* /*
@ -68,20 +68,6 @@ typedef struct xfs_inobt_key {
/* btree pointer type */ /* btree pointer type */
typedef __be32 xfs_inobt_ptr_t; typedef __be32 xfs_inobt_ptr_t;
/*
* Bit manipulations for ir_free.
*/
#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i))
#define XFS_INOBT_IS_FREE(rp,i) \
(((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
#define XFS_INOBT_SET_FREE(rp,i) ((rp)->ir_free |= XFS_INOBT_MASK(i))
#define XFS_INOBT_CLR_FREE(rp,i) ((rp)->ir_free &= ~XFS_INOBT_MASK(i))
/*
* Maximum number of inode btree levels.
*/
#define XFS_IN_MAXLEVELS(mp) ((mp)->m_in_maxlevels)
/* /*
* block numbers in the AG. * block numbers in the AG.
*/ */

View file

@ -122,7 +122,7 @@ typedef struct xfs_ictimestamp {
/* /*
* NOTE: This structure must be kept identical to struct xfs_dinode * NOTE: This structure must be kept identical to struct xfs_dinode
* in xfs_dinode.h except for the endianess annotations. * in xfs_dinode.h except for the endianness annotations.
*/ */
typedef struct xfs_icdinode { typedef struct xfs_icdinode {
__uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */

View file

@ -40,7 +40,6 @@ typedef struct xfs_inode_log_format {
__int32_t ilf_boffset; /* off of inode in buffer */ __int32_t ilf_boffset; /* off of inode in buffer */
} xfs_inode_log_format_t; } xfs_inode_log_format_t;
#ifndef HAVE_FORMAT32
typedef struct xfs_inode_log_format_32 { typedef struct xfs_inode_log_format_32 {
__uint16_t ilf_type; /* inode log item type */ __uint16_t ilf_type; /* inode log item type */
__uint16_t ilf_size; /* size of this item */ __uint16_t ilf_size; /* size of this item */
@ -56,7 +55,6 @@ typedef struct xfs_inode_log_format_32 {
__int32_t ilf_len; /* len of inode buffer */ __int32_t ilf_len; /* len of inode buffer */
__int32_t ilf_boffset; /* off of inode in buffer */ __int32_t ilf_boffset; /* off of inode in buffer */
} __attribute__((packed)) xfs_inode_log_format_32_t; } __attribute__((packed)) xfs_inode_log_format_32_t;
#endif
typedef struct xfs_inode_log_format_64 { typedef struct xfs_inode_log_format_64 {
__uint16_t ilf_type; /* inode log item type */ __uint16_t ilf_type; /* inode log item type */

View file

@ -63,7 +63,7 @@ typedef enum {
*/ */
typedef struct xfs_iomap { typedef struct xfs_iomap {
xfs_daddr_t iomap_bn; /* first 512b blk of mapping */ xfs_daddr_t iomap_bn; /* first 512B blk of mapping */
xfs_buftarg_t *iomap_target; xfs_buftarg_t *iomap_target;
xfs_off_t iomap_offset; /* offset of mapping, bytes */ xfs_off_t iomap_offset; /* offset of mapping, bytes */
xfs_off_t iomap_bsize; /* size of mapping, bytes */ xfs_off_t iomap_bsize; /* size of mapping, bytes */

View file

@ -83,7 +83,12 @@ xfs_bulkstat_one_iget(
buf->bs_uid = dic->di_uid; buf->bs_uid = dic->di_uid;
buf->bs_gid = dic->di_gid; buf->bs_gid = dic->di_gid;
buf->bs_size = dic->di_size; buf->bs_size = dic->di_size;
vn_atime_to_bstime(VFS_I(ip), &buf->bs_atime); /*
* We are reading the atime from the Linux inode because the
* dinode might not be uptodate.
*/
buf->bs_atime.tv_sec = VFS_I(ip)->i_atime.tv_sec;
buf->bs_atime.tv_nsec = VFS_I(ip)->i_atime.tv_nsec;
buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; buf->bs_mtime.tv_sec = dic->di_mtime.t_sec;
buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec;
buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; buf->bs_ctime.tv_sec = dic->di_ctime.t_sec;
@ -579,7 +584,7 @@ xfs_bulkstat(
* first inode of the cluster. * first inode of the cluster.
* *
* Careful with clustidx. There can be * Careful with clustidx. There can be
* multple clusters per chunk, a single * multiple clusters per chunk, a single
* cluster per chunk or a cluster that has * cluster per chunk or a cluster that has
* inodes represented from several different * inodes represented from several different
* chunks (if blocksize is large). * chunks (if blocksize is large).

View file

@ -574,7 +574,7 @@ xfs_log_mount(
error = xfs_trans_ail_init(mp); error = xfs_trans_ail_init(mp);
if (error) { if (error) {
cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error);
goto error; goto out_free_log;
} }
mp->m_log->l_ailp = mp->m_ail; mp->m_log->l_ailp = mp->m_ail;
@ -594,20 +594,22 @@ xfs_log_mount(
mp->m_flags |= XFS_MOUNT_RDONLY; mp->m_flags |= XFS_MOUNT_RDONLY;
if (error) { if (error) {
cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
goto error; goto out_destroy_ail;
} }
} }
/* Normal transactions can now occur */ /* Normal transactions can now occur */
mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY; mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
/* End mounting message in xfs_log_mount_finish */
return 0; return 0;
error:
xfs_log_unmount_dealloc(mp); out_destroy_ail:
xfs_trans_ail_destroy(mp);
out_free_log:
xlog_dealloc_log(mp->m_log);
out: out:
return error; return error;
} /* xfs_log_mount */ }
/* /*
* Finish the recovery of the file system. This is separate from * Finish the recovery of the file system. This is separate from
@ -632,19 +634,6 @@ xfs_log_mount_finish(xfs_mount_t *mp)
return error; return error;
} }
/*
* Unmount processing for the log.
*/
int
xfs_log_unmount(xfs_mount_t *mp)
{
int error;
error = xfs_log_unmount_write(mp);
xfs_log_unmount_dealloc(mp);
return error;
}
/* /*
* Final log writes as part of unmount. * Final log writes as part of unmount.
* *
@ -795,7 +784,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
* and deallocate the log as the aild references the log. * and deallocate the log as the aild references the log.
*/ */
void void
xfs_log_unmount_dealloc(xfs_mount_t *mp) xfs_log_unmount(xfs_mount_t *mp)
{ {
xfs_trans_ail_destroy(mp); xfs_trans_ail_destroy(mp);
xlog_dealloc_log(mp->m_log); xlog_dealloc_log(mp->m_log);
@ -1109,7 +1098,7 @@ xlog_bdstrat_cb(struct xfs_buf *bp)
/* /*
* Return size of each in-core log record buffer. * Return size of each in-core log record buffer.
* *
* All machines get 8 x 32KB buffers by default, unless tuned otherwise. * All machines get 8 x 32kB buffers by default, unless tuned otherwise.
* *
* If the filesystem blocksize is too large, we may need to choose a * If the filesystem blocksize is too large, we may need to choose a
* larger size since the directory code currently logs entire blocks. * larger size since the directory code currently logs entire blocks.
@ -1139,8 +1128,8 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp,
} }
if (xfs_sb_version_haslogv2(&mp->m_sb)) { if (xfs_sb_version_haslogv2(&mp->m_sb)) {
/* # headers = size / 32K /* # headers = size / 32k
* one header holds cycles from 32K of data * one header holds cycles from 32k of data
*/ */
xhdrs = mp->m_logbsize / XLOG_HEADER_CYCLE_SIZE; xhdrs = mp->m_logbsize / XLOG_HEADER_CYCLE_SIZE;
@ -1156,7 +1145,7 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp,
goto done; goto done;
} }
/* All machines use 32KB buffers by default. */ /* All machines use 32kB buffers by default. */
log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT; log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
@ -1164,32 +1153,8 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp,
log->l_iclog_hsize = BBSIZE; log->l_iclog_hsize = BBSIZE;
log->l_iclog_heads = 1; log->l_iclog_heads = 1;
/* done:
* For 16KB, we use 3 32KB buffers. For 32KB block sizes, we use /* are we being asked to make the sizes selected above visible? */
* 4 32KB buffers. For 64KB block sizes, we use 8 32KB buffers.
*/
if (mp->m_sb.sb_blocksize >= 16*1024) {
log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
if (mp->m_logbufs <= 0) {
switch (mp->m_sb.sb_blocksize) {
case 16*1024: /* 16 KB */
log->l_iclog_bufs = 3;
break;
case 32*1024: /* 32 KB */
log->l_iclog_bufs = 4;
break;
case 64*1024: /* 64 KB */
log->l_iclog_bufs = 8;
break;
default:
xlog_panic("XFS: Invalid blocksize");
break;
}
}
}
done: /* are we being asked to make the sizes selected above visible? */
if (mp->m_logbufs == 0) if (mp->m_logbufs == 0)
mp->m_logbufs = log->l_iclog_bufs; mp->m_logbufs = log->l_iclog_bufs;
if (mp->m_logbsize == 0) if (mp->m_logbsize == 0)
@ -3214,7 +3179,7 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
*/ */
/* /*
* Free a used ticket when it's refcount falls to zero. * Free a used ticket when its refcount falls to zero.
*/ */
void void
xfs_log_ticket_put( xfs_log_ticket_put(

View file

@ -170,9 +170,8 @@ int xfs_log_write(struct xfs_mount *mp,
int nentries, int nentries,
xfs_log_ticket_t ticket, xfs_log_ticket_t ticket,
xfs_lsn_t *start_lsn); xfs_lsn_t *start_lsn);
int xfs_log_unmount(struct xfs_mount *mp);
int xfs_log_unmount_write(struct xfs_mount *mp); int xfs_log_unmount_write(struct xfs_mount *mp);
void xfs_log_unmount_dealloc(struct xfs_mount *mp); void xfs_log_unmount(struct xfs_mount *mp);
int xfs_log_force_umount(struct xfs_mount *mp, int logerror); int xfs_log_force_umount(struct xfs_mount *mp, int logerror);
int xfs_log_need_covered(struct xfs_mount *mp); int xfs_log_need_covered(struct xfs_mount *mp);

View file

@ -359,7 +359,7 @@ typedef struct xlog_in_core {
int ic_size; int ic_size;
int ic_offset; int ic_offset;
int ic_bwritecnt; int ic_bwritecnt;
ushort_t ic_state; unsigned short ic_state;
char *ic_datap; /* pointer to iclog data */ char *ic_datap; /* pointer to iclog data */
#ifdef XFS_LOG_TRACE #ifdef XFS_LOG_TRACE
struct ktrace *ic_trace; struct ktrace *ic_trace;
@ -455,7 +455,6 @@ extern void xlog_recover_process_iunlinks(xlog_t *log);
extern struct xfs_buf *xlog_get_bp(xlog_t *, int); extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
extern void xlog_put_bp(struct xfs_buf *); extern void xlog_put_bp(struct xfs_buf *);
extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
extern kmem_zone_t *xfs_log_ticket_zone; extern kmem_zone_t *xfs_log_ticket_zone;

View file

@ -94,12 +94,30 @@ xlog_put_bp(
xfs_buf_free(bp); xfs_buf_free(bp);
} }
STATIC xfs_caddr_t
xlog_align(
xlog_t *log,
xfs_daddr_t blk_no,
int nbblks,
xfs_buf_t *bp)
{
xfs_caddr_t ptr;
if (!log->l_sectbb_log)
return XFS_BUF_PTR(bp);
ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
ASSERT(XFS_BUF_SIZE(bp) >=
BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
return ptr;
}
/* /*
* nbblks should be uint, but oh well. Just want to catch that 32-bit length. * nbblks should be uint, but oh well. Just want to catch that 32-bit length.
*/ */
int STATIC int
xlog_bread( xlog_bread_noalign(
xlog_t *log, xlog_t *log,
xfs_daddr_t blk_no, xfs_daddr_t blk_no,
int nbblks, int nbblks,
@ -137,6 +155,24 @@ xlog_bread(
return error; return error;
} }
STATIC int
xlog_bread(
xlog_t *log,
xfs_daddr_t blk_no,
int nbblks,
xfs_buf_t *bp,
xfs_caddr_t *offset)
{
int error;
error = xlog_bread_noalign(log, blk_no, nbblks, bp);
if (error)
return error;
*offset = xlog_align(log, blk_no, nbblks, bp);
return 0;
}
/* /*
* Write out the buffer at the given block for the given number of blocks. * Write out the buffer at the given block for the given number of blocks.
* The buffer is kept locked across the write and is returned locked. * The buffer is kept locked across the write and is returned locked.
@ -180,24 +216,6 @@ xlog_bwrite(
return error; return error;
} }
STATIC xfs_caddr_t
xlog_align(
xlog_t *log,
xfs_daddr_t blk_no,
int nbblks,
xfs_buf_t *bp)
{
xfs_caddr_t ptr;
if (!log->l_sectbb_log)
return XFS_BUF_PTR(bp);
ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
ASSERT(XFS_BUF_SIZE(bp) >=
BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
return ptr;
}
#ifdef DEBUG #ifdef DEBUG
/* /*
* dump debug superblock and log record information * dump debug superblock and log record information
@ -211,11 +229,11 @@ xlog_header_check_dump(
cmn_err(CE_DEBUG, "%s: SB : uuid = ", __func__); cmn_err(CE_DEBUG, "%s: SB : uuid = ", __func__);
for (b = 0; b < 16; b++) for (b = 0; b < 16; b++)
cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]); cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&mp->m_sb.sb_uuid)[b]);
cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT); cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT);
cmn_err(CE_DEBUG, " log : uuid = "); cmn_err(CE_DEBUG, " log : uuid = ");
for (b = 0; b < 16; b++) for (b = 0; b < 16; b++)
cmn_err(CE_DEBUG, "%02x",((uchar_t *)&head->h_fs_uuid)[b]); cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&head->h_fs_uuid)[b]);
cmn_err(CE_DEBUG, ", fmt = %d\n", be32_to_cpu(head->h_fmt)); cmn_err(CE_DEBUG, ", fmt = %d\n", be32_to_cpu(head->h_fmt));
} }
#else #else
@ -321,9 +339,9 @@ xlog_find_cycle_start(
mid_blk = BLK_AVG(first_blk, *last_blk); mid_blk = BLK_AVG(first_blk, *last_blk);
while (mid_blk != first_blk && mid_blk != *last_blk) { while (mid_blk != first_blk && mid_blk != *last_blk) {
if ((error = xlog_bread(log, mid_blk, 1, bp))) error = xlog_bread(log, mid_blk, 1, bp, &offset);
if (error)
return error; return error;
offset = xlog_align(log, mid_blk, 1, bp);
mid_cycle = xlog_get_cycle(offset); mid_cycle = xlog_get_cycle(offset);
if (mid_cycle == cycle) { if (mid_cycle == cycle) {
*last_blk = mid_blk; *last_blk = mid_blk;
@ -379,10 +397,10 @@ xlog_find_verify_cycle(
bcount = min(bufblks, (start_blk + nbblks - i)); bcount = min(bufblks, (start_blk + nbblks - i));
if ((error = xlog_bread(log, i, bcount, bp))) error = xlog_bread(log, i, bcount, bp, &buf);
if (error)
goto out; goto out;
buf = xlog_align(log, i, bcount, bp);
for (j = 0; j < bcount; j++) { for (j = 0; j < bcount; j++) {
cycle = xlog_get_cycle(buf); cycle = xlog_get_cycle(buf);
if (cycle == stop_on_cycle_no) { if (cycle == stop_on_cycle_no) {
@ -436,9 +454,9 @@ xlog_find_verify_log_record(
return ENOMEM; return ENOMEM;
smallmem = 1; smallmem = 1;
} else { } else {
if ((error = xlog_bread(log, start_blk, num_blks, bp))) error = xlog_bread(log, start_blk, num_blks, bp, &offset);
if (error)
goto out; goto out;
offset = xlog_align(log, start_blk, num_blks, bp);
offset += ((num_blks - 1) << BBSHIFT); offset += ((num_blks - 1) << BBSHIFT);
} }
@ -453,9 +471,9 @@ xlog_find_verify_log_record(
} }
if (smallmem) { if (smallmem) {
if ((error = xlog_bread(log, i, 1, bp))) error = xlog_bread(log, i, 1, bp, &offset);
if (error)
goto out; goto out;
offset = xlog_align(log, i, 1, bp);
} }
head = (xlog_rec_header_t *)offset; head = (xlog_rec_header_t *)offset;
@ -559,15 +577,18 @@ xlog_find_head(
bp = xlog_get_bp(log, 1); bp = xlog_get_bp(log, 1);
if (!bp) if (!bp)
return ENOMEM; return ENOMEM;
if ((error = xlog_bread(log, 0, 1, bp)))
error = xlog_bread(log, 0, 1, bp, &offset);
if (error)
goto bp_err; goto bp_err;
offset = xlog_align(log, 0, 1, bp);
first_half_cycle = xlog_get_cycle(offset); first_half_cycle = xlog_get_cycle(offset);
last_blk = head_blk = log_bbnum - 1; /* get cycle # of last block */ last_blk = head_blk = log_bbnum - 1; /* get cycle # of last block */
if ((error = xlog_bread(log, last_blk, 1, bp))) error = xlog_bread(log, last_blk, 1, bp, &offset);
if (error)
goto bp_err; goto bp_err;
offset = xlog_align(log, last_blk, 1, bp);
last_half_cycle = xlog_get_cycle(offset); last_half_cycle = xlog_get_cycle(offset);
ASSERT(last_half_cycle != 0); ASSERT(last_half_cycle != 0);
@ -817,9 +838,10 @@ xlog_find_tail(
if (!bp) if (!bp)
return ENOMEM; return ENOMEM;
if (*head_blk == 0) { /* special case */ if (*head_blk == 0) { /* special case */
if ((error = xlog_bread(log, 0, 1, bp))) error = xlog_bread(log, 0, 1, bp, &offset);
if (error)
goto bread_err; goto bread_err;
offset = xlog_align(log, 0, 1, bp);
if (xlog_get_cycle(offset) == 0) { if (xlog_get_cycle(offset) == 0) {
*tail_blk = 0; *tail_blk = 0;
/* leave all other log inited values alone */ /* leave all other log inited values alone */
@ -832,9 +854,10 @@ xlog_find_tail(
*/ */
ASSERT(*head_blk < INT_MAX); ASSERT(*head_blk < INT_MAX);
for (i = (int)(*head_blk) - 1; i >= 0; i--) { for (i = (int)(*head_blk) - 1; i >= 0; i--) {
if ((error = xlog_bread(log, i, 1, bp))) error = xlog_bread(log, i, 1, bp, &offset);
if (error)
goto bread_err; goto bread_err;
offset = xlog_align(log, i, 1, bp);
if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) { if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) {
found = 1; found = 1;
break; break;
@ -848,9 +871,10 @@ xlog_find_tail(
*/ */
if (!found) { if (!found) {
for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) { for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) {
if ((error = xlog_bread(log, i, 1, bp))) error = xlog_bread(log, i, 1, bp, &offset);
if (error)
goto bread_err; goto bread_err;
offset = xlog_align(log, i, 1, bp);
if (XLOG_HEADER_MAGIC_NUM == if (XLOG_HEADER_MAGIC_NUM ==
be32_to_cpu(*(__be32 *)offset)) { be32_to_cpu(*(__be32 *)offset)) {
found = 2; found = 2;
@ -922,10 +946,10 @@ xlog_find_tail(
if (*head_blk == after_umount_blk && if (*head_blk == after_umount_blk &&
be32_to_cpu(rhead->h_num_logops) == 1) { be32_to_cpu(rhead->h_num_logops) == 1) {
umount_data_blk = (i + hblks) % log->l_logBBsize; umount_data_blk = (i + hblks) % log->l_logBBsize;
if ((error = xlog_bread(log, umount_data_blk, 1, bp))) { error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
if (error)
goto bread_err; goto bread_err;
}
offset = xlog_align(log, umount_data_blk, 1, bp);
op_head = (xlog_op_header_t *)offset; op_head = (xlog_op_header_t *)offset;
if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) { if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) {
/* /*
@ -1017,9 +1041,10 @@ xlog_find_zeroed(
bp = xlog_get_bp(log, 1); bp = xlog_get_bp(log, 1);
if (!bp) if (!bp)
return ENOMEM; return ENOMEM;
if ((error = xlog_bread(log, 0, 1, bp))) error = xlog_bread(log, 0, 1, bp, &offset);
if (error)
goto bp_err; goto bp_err;
offset = xlog_align(log, 0, 1, bp);
first_cycle = xlog_get_cycle(offset); first_cycle = xlog_get_cycle(offset);
if (first_cycle == 0) { /* completely zeroed log */ if (first_cycle == 0) { /* completely zeroed log */
*blk_no = 0; *blk_no = 0;
@ -1028,9 +1053,10 @@ xlog_find_zeroed(
} }
/* check partially zeroed log */ /* check partially zeroed log */
if ((error = xlog_bread(log, log_bbnum-1, 1, bp))) error = xlog_bread(log, log_bbnum-1, 1, bp, &offset);
if (error)
goto bp_err; goto bp_err;
offset = xlog_align(log, log_bbnum-1, 1, bp);
last_cycle = xlog_get_cycle(offset); last_cycle = xlog_get_cycle(offset);
if (last_cycle != 0) { /* log completely written to */ if (last_cycle != 0) { /* log completely written to */
xlog_put_bp(bp); xlog_put_bp(bp);
@ -1152,10 +1178,10 @@ xlog_write_log_records(
*/ */
balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block); balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block);
if (balign != start_block) { if (balign != start_block) {
if ((error = xlog_bread(log, start_block, 1, bp))) { error = xlog_bread_noalign(log, start_block, 1, bp);
xlog_put_bp(bp); if (error)
return error; goto out_put_bp;
}
j = start_block - balign; j = start_block - balign;
} }
@ -1175,10 +1201,14 @@ xlog_write_log_records(
balign = BBTOB(ealign - start_block); balign = BBTOB(ealign - start_block);
error = XFS_BUF_SET_PTR(bp, offset + balign, error = XFS_BUF_SET_PTR(bp, offset + balign,
BBTOB(sectbb)); BBTOB(sectbb));
if (!error) if (error)
error = xlog_bread(log, ealign, sectbb, bp); break;
if (!error)
error = XFS_BUF_SET_PTR(bp, offset, bufblks); error = xlog_bread_noalign(log, ealign, sectbb, bp);
if (error)
break;
error = XFS_BUF_SET_PTR(bp, offset, bufblks);
if (error) if (error)
break; break;
} }
@ -1195,6 +1225,8 @@ xlog_write_log_records(
start_block += endcount; start_block += endcount;
j = 0; j = 0;
} }
out_put_bp:
xlog_put_bp(bp); xlog_put_bp(bp);
return error; return error;
} }
@ -2511,16 +2543,10 @@ xlog_recover_do_inode_trans(
} }
write_inode_buffer: write_inode_buffer:
if (ITEM_TYPE(item) == XFS_LI_INODE) { ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
ASSERT(bp->b_mount == NULL || bp->b_mount == mp); bp->b_mount = mp;
bp->b_mount = mp; XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); xfs_bdwrite(mp, bp);
xfs_bdwrite(mp, bp);
} else {
XFS_BUF_STALE(bp);
error = xfs_bwrite(mp, bp);
}
error: error:
if (need_free) if (need_free)
kmem_free(in_f); kmem_free(in_f);
@ -2769,51 +2795,48 @@ xlog_recover_do_trans(
int error = 0; int error = 0;
xlog_recover_item_t *item, *first_item; xlog_recover_item_t *item, *first_item;
if ((error = xlog_recover_reorder_trans(trans))) error = xlog_recover_reorder_trans(trans);
if (error)
return error; return error;
first_item = item = trans->r_itemq; first_item = item = trans->r_itemq;
do { do {
/* switch (ITEM_TYPE(item)) {
* we don't need to worry about the block number being case XFS_LI_BUF:
* truncated in > 1 TB buffers because in user-land, error = xlog_recover_do_buffer_trans(log, item, pass);
* we're now n32 or 64-bit so xfs_daddr_t is 64-bits so break;
* the blknos will get through the user-mode buffer case XFS_LI_INODE:
* cache properly. The only bad case is o32 kernels error = xlog_recover_do_inode_trans(log, item, pass);
* where xfs_daddr_t is 32-bits but mount will warn us break;
* off a > 1 TB filesystem before we get here. case XFS_LI_EFI:
*/ error = xlog_recover_do_efi_trans(log, item,
if ((ITEM_TYPE(item) == XFS_LI_BUF)) { trans->r_lsn, pass);
if ((error = xlog_recover_do_buffer_trans(log, item, break;
pass))) case XFS_LI_EFD:
break;
} else if ((ITEM_TYPE(item) == XFS_LI_INODE)) {
if ((error = xlog_recover_do_inode_trans(log, item,
pass)))
break;
} else if (ITEM_TYPE(item) == XFS_LI_EFI) {
if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn,
pass)))
break;
} else if (ITEM_TYPE(item) == XFS_LI_EFD) {
xlog_recover_do_efd_trans(log, item, pass); xlog_recover_do_efd_trans(log, item, pass);
} else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { error = 0;
if ((error = xlog_recover_do_dquot_trans(log, item, break;
pass))) case XFS_LI_DQUOT:
break; error = xlog_recover_do_dquot_trans(log, item, pass);
} else if ((ITEM_TYPE(item) == XFS_LI_QUOTAOFF)) { break;
if ((error = xlog_recover_do_quotaoff_trans(log, item, case XFS_LI_QUOTAOFF:
pass))) error = xlog_recover_do_quotaoff_trans(log, item,
break; pass);
} else { break;
xlog_warn("XFS: xlog_recover_do_trans"); default:
xlog_warn(
"XFS: invalid item type (%d) xlog_recover_do_trans", ITEM_TYPE(item));
ASSERT(0); ASSERT(0);
error = XFS_ERROR(EIO); error = XFS_ERROR(EIO);
break; break;
} }
if (error)
return error;
item = item->ri_next; item = item->ri_next;
} while (first_item != item); } while (first_item != item);
return error; return 0;
} }
/* /*
@ -3490,9 +3513,11 @@ xlog_do_recovery_pass(
hbp = xlog_get_bp(log, 1); hbp = xlog_get_bp(log, 1);
if (!hbp) if (!hbp)
return ENOMEM; return ENOMEM;
if ((error = xlog_bread(log, tail_blk, 1, hbp)))
error = xlog_bread(log, tail_blk, 1, hbp, &offset);
if (error)
goto bread_err1; goto bread_err1;
offset = xlog_align(log, tail_blk, 1, hbp);
rhead = (xlog_rec_header_t *)offset; rhead = (xlog_rec_header_t *)offset;
error = xlog_valid_rec_header(log, rhead, tail_blk); error = xlog_valid_rec_header(log, rhead, tail_blk);
if (error) if (error)
@ -3526,9 +3551,10 @@ xlog_do_recovery_pass(
memset(rhash, 0, sizeof(rhash)); memset(rhash, 0, sizeof(rhash));
if (tail_blk <= head_blk) { if (tail_blk <= head_blk) {
for (blk_no = tail_blk; blk_no < head_blk; ) { for (blk_no = tail_blk; blk_no < head_blk; ) {
if ((error = xlog_bread(log, blk_no, hblks, hbp))) error = xlog_bread(log, blk_no, hblks, hbp, &offset);
if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no, hblks, hbp);
rhead = (xlog_rec_header_t *)offset; rhead = (xlog_rec_header_t *)offset;
error = xlog_valid_rec_header(log, rhead, blk_no); error = xlog_valid_rec_header(log, rhead, blk_no);
if (error) if (error)
@ -3536,10 +3562,11 @@ xlog_do_recovery_pass(
/* blocks in data section */ /* blocks in data section */
bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
error = xlog_bread(log, blk_no + hblks, bblks, dbp); error = xlog_bread(log, blk_no + hblks, bblks, dbp,
&offset);
if (error) if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no + hblks, bblks, dbp);
xlog_unpack_data(rhead, offset, log); xlog_unpack_data(rhead, offset, log);
if ((error = xlog_recover_process_data(log, if ((error = xlog_recover_process_data(log,
rhash, rhead, offset, pass))) rhash, rhead, offset, pass)))
@ -3562,10 +3589,10 @@ xlog_do_recovery_pass(
wrapped_hblks = 0; wrapped_hblks = 0;
if (blk_no + hblks <= log->l_logBBsize) { if (blk_no + hblks <= log->l_logBBsize) {
/* Read header in one read */ /* Read header in one read */
error = xlog_bread(log, blk_no, hblks, hbp); error = xlog_bread(log, blk_no, hblks, hbp,
&offset);
if (error) if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no, hblks, hbp);
} else { } else {
/* This LR is split across physical log end */ /* This LR is split across physical log end */
if (blk_no != log->l_logBBsize) { if (blk_no != log->l_logBBsize) {
@ -3573,12 +3600,13 @@ xlog_do_recovery_pass(
ASSERT(blk_no <= INT_MAX); ASSERT(blk_no <= INT_MAX);
split_hblks = log->l_logBBsize - (int)blk_no; split_hblks = log->l_logBBsize - (int)blk_no;
ASSERT(split_hblks > 0); ASSERT(split_hblks > 0);
if ((error = xlog_bread(log, blk_no, error = xlog_bread(log, blk_no,
split_hblks, hbp))) split_hblks, hbp,
&offset);
if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no,
split_hblks, hbp);
} }
/* /*
* Note: this black magic still works with * Note: this black magic still works with
* large sector sizes (non-512) only because: * large sector sizes (non-512) only because:
@ -3596,14 +3624,19 @@ xlog_do_recovery_pass(
error = XFS_BUF_SET_PTR(hbp, error = XFS_BUF_SET_PTR(hbp,
bufaddr + BBTOB(split_hblks), bufaddr + BBTOB(split_hblks),
BBTOB(hblks - split_hblks)); BBTOB(hblks - split_hblks));
if (!error) if (error)
error = xlog_bread(log, 0, goto bread_err2;
wrapped_hblks, hbp);
if (!error) error = xlog_bread_noalign(log, 0,
error = XFS_BUF_SET_PTR(hbp, bufaddr, wrapped_hblks, hbp);
if (error)
goto bread_err2;
error = XFS_BUF_SET_PTR(hbp, bufaddr,
BBTOB(hblks)); BBTOB(hblks));
if (error) if (error)
goto bread_err2; goto bread_err2;
if (!offset) if (!offset)
offset = xlog_align(log, 0, offset = xlog_align(log, 0,
wrapped_hblks, hbp); wrapped_hblks, hbp);
@ -3619,10 +3652,10 @@ xlog_do_recovery_pass(
/* Read in data for log record */ /* Read in data for log record */
if (blk_no + bblks <= log->l_logBBsize) { if (blk_no + bblks <= log->l_logBBsize) {
error = xlog_bread(log, blk_no, bblks, dbp); error = xlog_bread(log, blk_no, bblks, dbp,
&offset);
if (error) if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no, bblks, dbp);
} else { } else {
/* This log record is split across the /* This log record is split across the
* physical end of log */ * physical end of log */
@ -3636,12 +3669,13 @@ xlog_do_recovery_pass(
split_bblks = split_bblks =
log->l_logBBsize - (int)blk_no; log->l_logBBsize - (int)blk_no;
ASSERT(split_bblks > 0); ASSERT(split_bblks > 0);
if ((error = xlog_bread(log, blk_no, error = xlog_bread(log, blk_no,
split_bblks, dbp))) split_bblks, dbp,
&offset);
if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no,
split_bblks, dbp);
} }
/* /*
* Note: this black magic still works with * Note: this black magic still works with
* large sector sizes (non-512) only because: * large sector sizes (non-512) only because:
@ -3658,15 +3692,19 @@ xlog_do_recovery_pass(
error = XFS_BUF_SET_PTR(dbp, error = XFS_BUF_SET_PTR(dbp,
bufaddr + BBTOB(split_bblks), bufaddr + BBTOB(split_bblks),
BBTOB(bblks - split_bblks)); BBTOB(bblks - split_bblks));
if (!error)
error = xlog_bread(log, wrapped_hblks,
bblks - split_bblks,
dbp);
if (!error)
error = XFS_BUF_SET_PTR(dbp, bufaddr,
h_size);
if (error) if (error)
goto bread_err2; goto bread_err2;
error = xlog_bread_noalign(log, wrapped_hblks,
bblks - split_bblks,
dbp);
if (error)
goto bread_err2;
error = XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
if (error)
goto bread_err2;
if (!offset) if (!offset)
offset = xlog_align(log, wrapped_hblks, offset = xlog_align(log, wrapped_hblks,
bblks - split_bblks, dbp); bblks - split_bblks, dbp);
@ -3683,17 +3721,21 @@ xlog_do_recovery_pass(
/* read first part of physical log */ /* read first part of physical log */
while (blk_no < head_blk) { while (blk_no < head_blk) {
if ((error = xlog_bread(log, blk_no, hblks, hbp))) error = xlog_bread(log, blk_no, hblks, hbp, &offset);
if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no, hblks, hbp);
rhead = (xlog_rec_header_t *)offset; rhead = (xlog_rec_header_t *)offset;
error = xlog_valid_rec_header(log, rhead, blk_no); error = xlog_valid_rec_header(log, rhead, blk_no);
if (error) if (error)
goto bread_err2; goto bread_err2;
bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp))) error = xlog_bread(log, blk_no+hblks, bblks, dbp,
&offset);
if (error)
goto bread_err2; goto bread_err2;
offset = xlog_align(log, blk_no+hblks, bblks, dbp);
xlog_unpack_data(rhead, offset, log); xlog_unpack_data(rhead, offset, log);
if ((error = xlog_recover_process_data(log, rhash, if ((error = xlog_recover_process_data(log, rhash,
rhead, offset, pass))) rhead, offset, pass)))

View file

@ -45,7 +45,6 @@
#include "xfs_fsops.h" #include "xfs_fsops.h"
#include "xfs_utils.h" #include "xfs_utils.h"
STATIC int xfs_uuid_mount(xfs_mount_t *);
STATIC void xfs_unmountfs_wait(xfs_mount_t *); STATIC void xfs_unmountfs_wait(xfs_mount_t *);
@ -121,6 +120,84 @@ static const struct {
{ sizeof(xfs_sb_t), 0 } { sizeof(xfs_sb_t), 0 }
}; };
static DEFINE_MUTEX(xfs_uuid_table_mutex);
static int xfs_uuid_table_size;
static uuid_t *xfs_uuid_table;
/*
* See if the UUID is unique among mounted XFS filesystems.
* Mount fails if UUID is nil or a FS with the same UUID is already mounted.
*/
STATIC int
xfs_uuid_mount(
struct xfs_mount *mp)
{
uuid_t *uuid = &mp->m_sb.sb_uuid;
int hole, i;
if (mp->m_flags & XFS_MOUNT_NOUUID)
return 0;
if (uuid_is_nil(uuid)) {
cmn_err(CE_WARN,
"XFS: Filesystem %s has nil UUID - can't mount",
mp->m_fsname);
return XFS_ERROR(EINVAL);
}
mutex_lock(&xfs_uuid_table_mutex);
for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) {
if (uuid_is_nil(&xfs_uuid_table[i])) {
hole = i;
continue;
}
if (uuid_equal(uuid, &xfs_uuid_table[i]))
goto out_duplicate;
}
if (hole < 0) {
xfs_uuid_table = kmem_realloc(xfs_uuid_table,
(xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table),
xfs_uuid_table_size * sizeof(*xfs_uuid_table),
KM_SLEEP);
hole = xfs_uuid_table_size++;
}
xfs_uuid_table[hole] = *uuid;
mutex_unlock(&xfs_uuid_table_mutex);
return 0;
out_duplicate:
mutex_unlock(&xfs_uuid_table_mutex);
cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount",
mp->m_fsname);
return XFS_ERROR(EINVAL);
}
STATIC void
xfs_uuid_unmount(
struct xfs_mount *mp)
{
uuid_t *uuid = &mp->m_sb.sb_uuid;
int i;
if (mp->m_flags & XFS_MOUNT_NOUUID)
return;
mutex_lock(&xfs_uuid_table_mutex);
for (i = 0; i < xfs_uuid_table_size; i++) {
if (uuid_is_nil(&xfs_uuid_table[i]))
continue;
if (!uuid_equal(uuid, &xfs_uuid_table[i]))
continue;
memset(&xfs_uuid_table[i], 0, sizeof(uuid_t));
break;
}
ASSERT(i < xfs_uuid_table_size);
mutex_unlock(&xfs_uuid_table_mutex);
}
/* /*
* Free up the resources associated with a mount structure. Assume that * Free up the resources associated with a mount structure. Assume that
* the structure was initially zeroed, so we can tell which fields got * the structure was initially zeroed, so we can tell which fields got
@ -256,6 +333,22 @@ xfs_mount_validate_sb(
return XFS_ERROR(ENOSYS); return XFS_ERROR(ENOSYS);
} }
/*
* Currently only very few inode sizes are supported.
*/
switch (sbp->sb_inodesize) {
case 256:
case 512:
case 1024:
case 2048:
break;
default:
xfs_fs_mount_cmn_err(flags,
"inode size of %d bytes not supported",
sbp->sb_inodesize);
return XFS_ERROR(ENOSYS);
}
if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
xfs_fs_mount_cmn_err(flags, xfs_fs_mount_cmn_err(flags,
@ -574,32 +667,10 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog; mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
mp->m_litino = sbp->sb_inodesize - sizeof(struct xfs_dinode);
mp->m_blockmask = sbp->sb_blocksize - 1; mp->m_blockmask = sbp->sb_blocksize - 1;
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1; mp->m_blockwmask = mp->m_blockwsize - 1;
/*
* Setup for attributes, in case they get created.
* This value is for inodes getting attributes for the first time,
* the per-inode value is for old attribute values.
*/
ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048);
switch (sbp->sb_inodesize) {
case 256:
mp->m_attroffset = XFS_LITINO(mp) -
XFS_BMDR_SPACE_CALC(MINABTPTRS);
break;
case 512:
case 1024:
case 2048:
mp->m_attroffset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
break;
default:
ASSERT(0);
}
ASSERT(mp->m_attroffset < XFS_LITINO(mp));
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2; mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2;
@ -645,7 +716,7 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
for (index = 0; index < agcount; index++) { for (index = 0; index < agcount; index++) {
/* /*
* read the agf, then the agi. This gets us * read the agf, then the agi. This gets us
* all the inforamtion we need and populates the * all the information we need and populates the
* per-ag structures for us. * per-ag structures for us.
*/ */
error = xfs_alloc_pagf_init(mp, NULL, index, 0); error = xfs_alloc_pagf_init(mp, NULL, index, 0);
@ -886,8 +957,6 @@ xfs_check_sizes(xfs_mount_t *mp)
} }
/* /*
* xfs_mountfs
*
* This function does the following on an initial mount of a file system: * This function does the following on an initial mount of a file system:
* - reads the superblock from disk and init the mount struct * - reads the superblock from disk and init the mount struct
* - if we're a 32-bit kernel, do a size check on the superblock * - if we're a 32-bit kernel, do a size check on the superblock
@ -905,7 +974,6 @@ xfs_mountfs(
xfs_inode_t *rip; xfs_inode_t *rip;
__uint64_t resblks; __uint64_t resblks;
uint quotamount, quotaflags; uint quotamount, quotaflags;
int uuid_mounted = 0;
int error = 0; int error = 0;
xfs_mount_common(mp, sbp); xfs_mount_common(mp, sbp);
@ -960,7 +1028,7 @@ xfs_mountfs(
*/ */
error = xfs_update_alignment(mp); error = xfs_update_alignment(mp);
if (error) if (error)
goto error1; goto out;
xfs_alloc_compute_maxlevels(mp); xfs_alloc_compute_maxlevels(mp);
xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
@ -971,19 +1039,9 @@ xfs_mountfs(
mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
/* error = xfs_uuid_mount(mp);
* XFS uses the uuid from the superblock as the unique if (error)
* identifier for fsid. We can not use the uuid from the volume goto out;
* since a single partition filesystem is identical to a single
* partition volume/filesystem.
*/
if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
if (xfs_uuid_mount(mp)) {
error = XFS_ERROR(EINVAL);
goto error1;
}
uuid_mounted=1;
}
/* /*
* Set the minimum read and write sizes * Set the minimum read and write sizes
@ -1007,7 +1065,7 @@ xfs_mountfs(
*/ */
error = xfs_check_sizes(mp); error = xfs_check_sizes(mp);
if (error) if (error)
goto error1; goto out_remove_uuid;
/* /*
* Initialize realtime fields in the mount structure * Initialize realtime fields in the mount structure
@ -1015,7 +1073,7 @@ xfs_mountfs(
error = xfs_rtmount_init(mp); error = xfs_rtmount_init(mp);
if (error) { if (error) {
cmn_err(CE_WARN, "XFS: RT mount failed"); cmn_err(CE_WARN, "XFS: RT mount failed");
goto error1; goto out_remove_uuid;
} }
/* /*
@ -1045,26 +1103,26 @@ xfs_mountfs(
mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t),
KM_MAYFAIL); KM_MAYFAIL);
if (!mp->m_perag) if (!mp->m_perag)
goto error1; goto out_remove_uuid;
mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
if (!sbp->sb_logblocks) {
cmn_err(CE_WARN, "XFS: no log defined");
XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp);
error = XFS_ERROR(EFSCORRUPTED);
goto out_free_perag;
}
/* /*
* log's mount-time initialization. Perform 1st part recovery if needed * log's mount-time initialization. Perform 1st part recovery if needed
*/ */
if (likely(sbp->sb_logblocks > 0)) { /* check for volume case */ error = xfs_log_mount(mp, mp->m_logdev_targp,
error = xfs_log_mount(mp, mp->m_logdev_targp, XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); if (error) {
if (error) { cmn_err(CE_WARN, "XFS: log mount failed");
cmn_err(CE_WARN, "XFS: log mount failed"); goto out_free_perag;
goto error2;
}
} else { /* No log has been defined */
cmn_err(CE_WARN, "XFS: no log defined");
XFS_ERROR_REPORT("xfs_mountfs_int(1)", XFS_ERRLEVEL_LOW, mp);
error = XFS_ERROR(EFSCORRUPTED);
goto error2;
} }
/* /*
@ -1086,15 +1144,14 @@ xfs_mountfs(
* If we are currently making the filesystem, the initialisation will * If we are currently making the filesystem, the initialisation will
* fail as the perag data is in an undefined state. * fail as the perag data is in an undefined state.
*/ */
if (xfs_sb_version_haslazysbcount(&mp->m_sb) && if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
!XFS_LAST_UNMOUNT_WAS_CLEAN(mp) && !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
!mp->m_sb.sb_inprogress) { !mp->m_sb.sb_inprogress) {
error = xfs_initialize_perag_data(mp, sbp->sb_agcount); error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
if (error) { if (error)
goto error2; goto out_free_perag;
}
} }
/* /*
* Get and sanity-check the root inode. * Get and sanity-check the root inode.
* Save the pointer to it in the mount structure. * Save the pointer to it in the mount structure.
@ -1102,7 +1159,7 @@ xfs_mountfs(
error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0); error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0);
if (error) { if (error) {
cmn_err(CE_WARN, "XFS: failed to read root inode"); cmn_err(CE_WARN, "XFS: failed to read root inode");
goto error3; goto out_log_dealloc;
} }
ASSERT(rip != NULL); ASSERT(rip != NULL);
@ -1116,7 +1173,7 @@ xfs_mountfs(
XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
mp); mp);
error = XFS_ERROR(EFSCORRUPTED); error = XFS_ERROR(EFSCORRUPTED);
goto error4; goto out_rele_rip;
} }
mp->m_rootip = rip; /* save it */ mp->m_rootip = rip; /* save it */
@ -1131,7 +1188,7 @@ xfs_mountfs(
* Free up the root inode. * Free up the root inode.
*/ */
cmn_err(CE_WARN, "XFS: failed to read RT inodes"); cmn_err(CE_WARN, "XFS: failed to read RT inodes");
goto error4; goto out_rele_rip;
} }
/* /*
@ -1143,7 +1200,7 @@ xfs_mountfs(
error = xfs_mount_log_sb(mp, mp->m_update_flags); error = xfs_mount_log_sb(mp, mp->m_update_flags);
if (error) { if (error) {
cmn_err(CE_WARN, "XFS: failed to write sb changes"); cmn_err(CE_WARN, "XFS: failed to write sb changes");
goto error4; goto out_rtunmount;
} }
} }
@ -1152,7 +1209,7 @@ xfs_mountfs(
*/ */
error = XFS_QM_INIT(mp, &quotamount, &quotaflags); error = XFS_QM_INIT(mp, &quotamount, &quotaflags);
if (error) if (error)
goto error4; goto out_rtunmount;
/* /*
* Finish recovering the file system. This part needed to be * Finish recovering the file system. This part needed to be
@ -1162,7 +1219,7 @@ xfs_mountfs(
error = xfs_log_mount_finish(mp); error = xfs_log_mount_finish(mp);
if (error) { if (error) {
cmn_err(CE_WARN, "XFS: log mount finish failed"); cmn_err(CE_WARN, "XFS: log mount finish failed");
goto error4; goto out_rtunmount;
} }
/* /*
@ -1170,7 +1227,7 @@ xfs_mountfs(
*/ */
error = XFS_QM_MOUNT(mp, quotamount, quotaflags); error = XFS_QM_MOUNT(mp, quotamount, quotaflags);
if (error) if (error)
goto error4; goto out_rtunmount;
/* /*
* Now we are mounted, reserve a small amount of unused space for * Now we are mounted, reserve a small amount of unused space for
@ -1194,18 +1251,17 @@ xfs_mountfs(
return 0; return 0;
error4: out_rtunmount:
/* xfs_rtunmount_inodes(mp);
* Free up the root inode. out_rele_rip:
*/
IRELE(rip); IRELE(rip);
error3: out_log_dealloc:
xfs_log_unmount_dealloc(mp); xfs_log_unmount(mp);
error2: out_free_perag:
xfs_free_perag(mp); xfs_free_perag(mp);
error1: out_remove_uuid:
if (uuid_mounted) xfs_uuid_unmount(mp);
uuid_table_remove(&mp->m_sb.sb_uuid); out:
return error; return error;
} }
@ -1226,15 +1282,12 @@ xfs_unmountfs(
*/ */
XFS_QM_UNMOUNT(mp); XFS_QM_UNMOUNT(mp);
if (mp->m_rbmip) xfs_rtunmount_inodes(mp);
IRELE(mp->m_rbmip);
if (mp->m_rsumip)
IRELE(mp->m_rsumip);
IRELE(mp->m_rootip); IRELE(mp->m_rootip);
/* /*
* We can potentially deadlock here if we have an inode cluster * We can potentially deadlock here if we have an inode cluster
* that has been freed has it's buffer still pinned in memory because * that has been freed has its buffer still pinned in memory because
* the transaction is still sitting in a iclog. The stale inodes * the transaction is still sitting in a iclog. The stale inodes
* on that buffer will have their flush locks held until the * on that buffer will have their flush locks held until the
* transaction hits the disk and the callbacks run. the inode * transaction hits the disk and the callbacks run. the inode
@ -1266,7 +1319,7 @@ xfs_unmountfs(
* Unreserve any blocks we have so that when we unmount we don't account * Unreserve any blocks we have so that when we unmount we don't account
* the reserved free space as used. This is really only necessary for * the reserved free space as used. This is really only necessary for
* lazy superblock counting because it trusts the incore superblock * lazy superblock counting because it trusts the incore superblock
* counters to be aboslutely correct on clean unmount. * counters to be absolutely correct on clean unmount.
* *
* We don't bother correcting this elsewhere for lazy superblock * We don't bother correcting this elsewhere for lazy superblock
* counting because on mount of an unclean filesystem we reconstruct the * counting because on mount of an unclean filesystem we reconstruct the
@ -1288,10 +1341,9 @@ xfs_unmountfs(
"Freespace may not be correct on next mount."); "Freespace may not be correct on next mount.");
xfs_unmountfs_writesb(mp); xfs_unmountfs_writesb(mp);
xfs_unmountfs_wait(mp); /* wait for async bufs */ xfs_unmountfs_wait(mp); /* wait for async bufs */
xfs_log_unmount(mp); /* Done! No more fs ops. */ xfs_log_unmount_write(mp);
xfs_log_unmount(mp);
if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) xfs_uuid_unmount(mp);
uuid_table_remove(&mp->m_sb.sb_uuid);
#if defined(DEBUG) #if defined(DEBUG)
xfs_errortag_clearall(mp, 0); xfs_errortag_clearall(mp, 0);
@ -1792,29 +1844,6 @@ xfs_freesb(
mp->m_sb_bp = NULL; mp->m_sb_bp = NULL;
} }
/*
* See if the UUID is unique among mounted XFS filesystems.
* Mount fails if UUID is nil or a FS with the same UUID is already mounted.
*/
STATIC int
xfs_uuid_mount(
xfs_mount_t *mp)
{
if (uuid_is_nil(&mp->m_sb.sb_uuid)) {
cmn_err(CE_WARN,
"XFS: Filesystem %s has nil UUID - can't mount",
mp->m_fsname);
return -1;
}
if (!uuid_table_insert(&mp->m_sb.sb_uuid)) {
cmn_err(CE_WARN,
"XFS: Filesystem %s has duplicate UUID - can't mount",
mp->m_fsname);
return -1;
}
return 0;
}
/* /*
* Used to log changes to the superblock unit and width fields which could * Used to log changes to the superblock unit and width fields which could
* be altered by the mount options, as well as any potential sb_features2 * be altered by the mount options, as well as any potential sb_features2
@ -1868,7 +1897,7 @@ xfs_mount_log_sb(
* we disable the per-cpu counter and go through the slow path. * we disable the per-cpu counter and go through the slow path.
* *
* The slow path is the current xfs_mod_incore_sb() function. This means that * The slow path is the current xfs_mod_incore_sb() function. This means that
* when we disable a per-cpu counter, we need to drain it's resources back to * when we disable a per-cpu counter, we need to drain its resources back to
* the global superblock. We do this after disabling the counter to prevent * the global superblock. We do this after disabling the counter to prevent
* more threads from queueing up on the counter. * more threads from queueing up on the counter.
* *

View file

@ -136,7 +136,6 @@ typedef int (*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *,
struct xfs_dquot *, struct xfs_dquot *, uint); struct xfs_dquot *, struct xfs_dquot *, uint);
typedef void (*xfs_dqstatvfs_t)(struct xfs_inode *, struct kstatfs *); typedef void (*xfs_dqstatvfs_t)(struct xfs_inode *, struct kstatfs *);
typedef int (*xfs_dqsync_t)(struct xfs_mount *, int flags); typedef int (*xfs_dqsync_t)(struct xfs_mount *, int flags);
typedef int (*xfs_quotactl_t)(struct xfs_mount *, int, int, xfs_caddr_t);
typedef struct xfs_qmops { typedef struct xfs_qmops {
xfs_qminit_t xfs_qminit; xfs_qminit_t xfs_qminit;
@ -154,7 +153,6 @@ typedef struct xfs_qmops {
xfs_dqvopchownresv_t xfs_dqvopchownresv; xfs_dqvopchownresv_t xfs_dqvopchownresv;
xfs_dqstatvfs_t xfs_dqstatvfs; xfs_dqstatvfs_t xfs_dqstatvfs;
xfs_dqsync_t xfs_dqsync; xfs_dqsync_t xfs_dqsync;
xfs_quotactl_t xfs_quotactl;
struct xfs_dqtrxops *xfs_dqtrxops; struct xfs_dqtrxops *xfs_dqtrxops;
} xfs_qmops_t; } xfs_qmops_t;
@ -188,8 +186,6 @@ typedef struct xfs_qmops {
(*(ip)->i_mount->m_qm_ops->xfs_dqstatvfs)(ip, statp) (*(ip)->i_mount->m_qm_ops->xfs_dqstatvfs)(ip, statp)
#define XFS_QM_DQSYNC(mp, flags) \ #define XFS_QM_DQSYNC(mp, flags) \
(*(mp)->m_qm_ops->xfs_dqsync)(mp, flags) (*(mp)->m_qm_ops->xfs_dqsync)(mp, flags)
#define XFS_QM_QUOTACTL(mp, cmd, id, addr) \
(*(mp)->m_qm_ops->xfs_quotactl)(mp, cmd, id, addr)
#ifdef HAVE_PERCPU_SB #ifdef HAVE_PERCPU_SB
@ -273,19 +269,17 @@ typedef struct xfs_mount {
uint m_inobt_mnr[2]; /* min inobt btree records */ uint m_inobt_mnr[2]; /* min inobt btree records */
uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */
uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */
uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */ uint m_in_maxlevels; /* max inobt btree levels. */
struct xfs_perag *m_perag; /* per-ag accounting info */ struct xfs_perag *m_perag; /* per-ag accounting info */
struct rw_semaphore m_peraglock; /* lock for m_perag (pointer) */ struct rw_semaphore m_peraglock; /* lock for m_perag (pointer) */
struct mutex m_growlock; /* growfs mutex */ struct mutex m_growlock; /* growfs mutex */
int m_fixedfsid[2]; /* unchanged for life of FS */ int m_fixedfsid[2]; /* unchanged for life of FS */
uint m_dmevmask; /* DMI events for this FS */ uint m_dmevmask; /* DMI events for this FS */
__uint64_t m_flags; /* global mount flags */ __uint64_t m_flags; /* global mount flags */
uint m_attroffset; /* inode attribute offset */
uint m_dir_node_ents; /* #entries in a dir danode */ uint m_dir_node_ents; /* #entries in a dir danode */
uint m_attr_node_ents; /* #entries in attr danode */ uint m_attr_node_ents; /* #entries in attr danode */
int m_ialloc_inos; /* inodes in inode allocation */ int m_ialloc_inos; /* inodes in inode allocation */
int m_ialloc_blks; /* blocks in inode allocation */ int m_ialloc_blks; /* blocks in inode allocation */
int m_litino; /* size of inode union area */
int m_inoalign_mask;/* mask sb_inoalignmt if used */ int m_inoalign_mask;/* mask sb_inoalignmt if used */
uint m_qflags; /* quota status flags */ uint m_qflags; /* quota status flags */
xfs_trans_reservations_t m_reservations;/* precomputed res values */ xfs_trans_reservations_t m_reservations;/* precomputed res values */
@ -293,9 +287,6 @@ typedef struct xfs_mount {
__uint64_t m_maxioffset; /* maximum inode offset */ __uint64_t m_maxioffset; /* maximum inode offset */
__uint64_t m_resblks; /* total reserved blocks */ __uint64_t m_resblks; /* total reserved blocks */
__uint64_t m_resblks_avail;/* available reserved blocks */ __uint64_t m_resblks_avail;/* available reserved blocks */
#if XFS_BIG_INUMS
xfs_ino_t m_inoadd; /* add value for ino64_offset */
#endif
int m_dalign; /* stripe unit */ int m_dalign; /* stripe unit */
int m_swidth; /* stripe width */ int m_swidth; /* stripe width */
int m_sinoalign; /* stripe unit inode alignment */ int m_sinoalign; /* stripe unit inode alignment */
@ -337,7 +328,6 @@ typedef struct xfs_mount {
#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 must be synchronous except
for space allocations */ for space allocations */
#define XFS_MOUNT_INO64 (1ULL << 1)
#define XFS_MOUNT_DMAPI (1ULL << 2) /* dmapi is enabled */ #define XFS_MOUNT_DMAPI (1ULL << 2) /* dmapi is enabled */
#define XFS_MOUNT_WAS_CLEAN (1ULL << 3) #define XFS_MOUNT_WAS_CLEAN (1ULL << 3)
#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
@ -389,8 +379,8 @@ typedef struct xfs_mount {
* Synchronous read and write sizes. This should be * Synchronous read and write sizes. This should be
* better for NFSv2 wsync filesystems. * better for NFSv2 wsync filesystems.
*/ */
#define XFS_WSYNC_READIO_LOG 15 /* 32K */ #define XFS_WSYNC_READIO_LOG 15 /* 32k */
#define XFS_WSYNC_WRITEIO_LOG 14 /* 16K */ #define XFS_WSYNC_WRITEIO_LOG 14 /* 16k */
/* /*
* Allow large block sizes to be reported to userspace programs if the * Allow large block sizes to be reported to userspace programs if the
@ -500,9 +490,6 @@ typedef struct xfs_mod_sb {
int64_t msb_delta; /* Change to make to specified field */ int64_t msb_delta; /* Change to make to specified field */
} xfs_mod_sb_t; } xfs_mod_sb_t;
#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock))
#define XFS_MOUNT_IUNLOCK(mp) mutex_unlock(&((mp)->m_ilock))
extern int xfs_log_sbcount(xfs_mount_t *, uint); extern int xfs_log_sbcount(xfs_mount_t *, uint);
extern int xfs_mountfs(xfs_mount_t *mp); extern int xfs_mountfs(xfs_mount_t *mp);
extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); extern void xfs_mountfs_check_barriers(xfs_mount_t *mp);

View file

@ -126,7 +126,6 @@ static struct xfs_qmops xfs_qmcore_stub = {
.xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr, .xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr,
.xfs_dqstatvfs = (xfs_dqstatvfs_t) fs_noval, .xfs_dqstatvfs = (xfs_dqstatvfs_t) fs_noval,
.xfs_dqsync = (xfs_dqsync_t) fs_noerr, .xfs_dqsync = (xfs_dqsync_t) fs_noerr,
.xfs_quotactl = (xfs_quotactl_t) fs_nosys,
}; };
int int

View file

@ -18,6 +18,8 @@
#ifndef __XFS_QUOTA_H__ #ifndef __XFS_QUOTA_H__
#define __XFS_QUOTA_H__ #define __XFS_QUOTA_H__
struct xfs_trans;
/* /*
* The ondisk form of a dquot structure. * The ondisk form of a dquot structure.
*/ */
@ -185,7 +187,6 @@ typedef struct xfs_qoff_logformat {
* to a single function. None of these XFS_QMOPT_* flags are meant to have * to a single function. None of these XFS_QMOPT_* flags are meant to have
* persistent values (ie. their values can and will change between versions) * persistent values (ie. their values can and will change between versions)
*/ */
#define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */
#define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */
#define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */
#define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */ #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */

View file

@ -2288,6 +2288,16 @@ xfs_rtmount_inodes(
return 0; return 0;
} }
void
xfs_rtunmount_inodes(
struct xfs_mount *mp)
{
if (mp->m_rbmip)
IRELE(mp->m_rbmip);
if (mp->m_rsumip)
IRELE(mp->m_rsumip);
}
/* /*
* Pick an extent for allocation at the start of a new realtime file. * Pick an extent for allocation at the start of a new realtime file.
* Use the sequence number stored in the atime field of the bitmap inode. * Use the sequence number stored in the atime field of the bitmap inode.

View file

@ -23,8 +23,8 @@ struct xfs_trans;
/* Min and max rt extent sizes, specified in bytes */ /* Min and max rt extent sizes, specified in bytes */
#define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */
#define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64KB */ #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */
#define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4KB */ #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */
/* /*
* Constants for bit manipulations. * Constants for bit manipulations.
@ -108,6 +108,9 @@ xfs_rtfree_extent(
int /* error */ int /* error */
xfs_rtmount_init( xfs_rtmount_init(
struct xfs_mount *mp); /* file system mount structure */ struct xfs_mount *mp); /* file system mount structure */
void
xfs_rtunmount_inodes(
struct xfs_mount *mp);
/* /*
* Get the bitmap and summary inodes into the mount structure * Get the bitmap and summary inodes into the mount structure
@ -146,6 +149,7 @@ xfs_growfs_rt(
# define xfs_growfs_rt(mp,in) (ENOSYS) # define xfs_growfs_rt(mp,in) (ENOSYS)
# define xfs_rtmount_init(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) # define xfs_rtmount_init(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) # define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
# define xfs_rtunmount_inodes(m)
#endif /* CONFIG_XFS_RT */ #endif /* CONFIG_XFS_RT */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */

View file

@ -292,7 +292,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
* In a write transaction we can allocate a maximum of 2 * In a write transaction we can allocate a maximum of 2
* extents. This gives: * extents. This gives:
* the inode getting the new extents: inode size * the inode getting the new extents: inode size
* the inode\'s bmap btree: max depth * block size * the inode's bmap btree: max depth * block size
* the agfs of the ags from which the extents are allocated: 2 * sector * the agfs of the ags from which the extents are allocated: 2 * sector
* the superblock free block counter: sector size * the superblock free block counter: sector size
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
@ -321,7 +321,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
/* /*
* In truncating a file we free up to two extents at once. We can modify: * In truncating a file we free up to two extents at once. We can modify:
* the inode being truncated: inode size * the inode being truncated: inode size
* the inode\'s bmap btree: (max depth + 1) * block size * the inode's bmap btree: (max depth + 1) * block size
* And the bmap_finish transaction can free the blocks and bmap blocks: * And the bmap_finish transaction can free the blocks and bmap blocks:
* the agf for each of the ags: 4 * sector size * the agf for each of the ags: 4 * sector size
* the agfl for each of the ags: 4 * sector size * the agfl for each of the ags: 4 * sector size
@ -343,7 +343,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
(128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \ (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \
(128 * 5) + \ (128 * 5) + \
XFS_ALLOCFREE_LOG_RES(mp, 1) + \ XFS_ALLOCFREE_LOG_RES(mp, 1) + \
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
#define XFS_ITRUNCATE_LOG_RES(mp) ((mp)->m_reservations.tr_itruncate) #define XFS_ITRUNCATE_LOG_RES(mp) ((mp)->m_reservations.tr_itruncate)
@ -431,8 +431,8 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
* the new inode: inode size * the new inode: inode size
* the inode btree entry: 1 block * the inode btree entry: 1 block
* the directory btree: (max depth + v2) * dir block size * the directory btree: (max depth + v2) * dir block size
* the directory inode\'s bmap btree: (max depth + v2) * block size * the directory inode's bmap btree: (max depth + v2) * block size
* the blocks for the symlink: 1 KB * the blocks for the symlink: 1 kB
* Or in the first xact we allocate some inodes giving: * Or in the first xact we allocate some inodes giving:
* the agi and agf of the ag getting the new inodes: 2 * sectorsize * the agi and agf of the ag getting the new inodes: 2 * sectorsize
* the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
@ -449,9 +449,9 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
(128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \ (128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \
(2 * (mp)->m_sb.sb_sectsize + \ (2 * (mp)->m_sb.sb_sectsize + \
XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \ XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
XFS_FSB_TO_B((mp), XFS_IN_MAXLEVELS(mp)) + \ XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
XFS_ALLOCFREE_LOG_RES(mp, 1) + \ XFS_ALLOCFREE_LOG_RES(mp, 1) + \
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
#define XFS_SYMLINK_LOG_RES(mp) ((mp)->m_reservations.tr_symlink) #define XFS_SYMLINK_LOG_RES(mp) ((mp)->m_reservations.tr_symlink)
@ -463,7 +463,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
* the inode btree entry: block size * the inode btree entry: block size
* the superblock for the nlink flag: sector size * the superblock for the nlink flag: sector size
* the directory btree: (max depth + v2) * dir block size * the directory btree: (max depth + v2) * dir block size
* the directory inode\'s bmap btree: (max depth + v2) * block size * the directory inode's bmap btree: (max depth + v2) * block size
* Or in the first xact we allocate some inodes giving: * Or in the first xact we allocate some inodes giving:
* the agi and agf of the ag getting the new inodes: 2 * sectorsize * the agi and agf of the ag getting the new inodes: 2 * sectorsize
* the superblock for the nlink flag: sector size * the superblock for the nlink flag: sector size
@ -481,9 +481,9 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
(128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \ (128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \
(3 * (mp)->m_sb.sb_sectsize + \ (3 * (mp)->m_sb.sb_sectsize + \
XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \ XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
XFS_FSB_TO_B((mp), XFS_IN_MAXLEVELS(mp)) + \ XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
XFS_ALLOCFREE_LOG_RES(mp, 1) + \ XFS_ALLOCFREE_LOG_RES(mp, 1) + \
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
#define XFS_CREATE_LOG_RES(mp) ((mp)->m_reservations.tr_create) #define XFS_CREATE_LOG_RES(mp) ((mp)->m_reservations.tr_create)
@ -513,7 +513,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \ MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \
(128 * 5) + \ (128 * 5) + \
XFS_ALLOCFREE_LOG_RES(mp, 1) + \ XFS_ALLOCFREE_LOG_RES(mp, 1) + \
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
@ -637,7 +637,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
/* /*
* Removing the attribute fork of a file * Removing the attribute fork of a file
* the inode being truncated: inode size * the inode being truncated: inode size
* the inode\'s bmap btree: max depth * block size * the inode's bmap btree: max depth * block size
* And the bmap_finish transaction can free the blocks and bmap blocks: * And the bmap_finish transaction can free the blocks and bmap blocks:
* the agf for each of the ags: 4 * sector size * the agf for each of the ags: 4 * sector size
* the agfl for each of the ags: 4 * sector size * the agfl for each of the ags: 4 * sector size

View file

@ -79,7 +79,7 @@ xfs_trans_ail_tail(
* the push is run asynchronously in a separate thread, so we return the tail * the push is run asynchronously in a separate thread, so we return the tail
* of the log right now instead of the tail after the push. This means we will * of the log right now instead of the tail after the push. This means we will
* either continue right away, or we will sleep waiting on the async thread to * either continue right away, or we will sleep waiting on the async thread to
* do it's work. * do its work.
* *
* We do this unlocked - we only need to know whether there is anything in the * We do this unlocked - we only need to know whether there is anything in the
* AIL at the time we are called. We don't need to access the contents of * AIL at the time we are called. We don't need to access the contents of
@ -160,7 +160,7 @@ xfs_trans_ail_cursor_next(
/* /*
* Now that the traversal is complete, we need to remove the cursor * Now that the traversal is complete, we need to remove the cursor
* from the list of traversing cursors. Avoid removing the embedded * from the list of traversing cursors. Avoid removing the embedded
* push cursor, but use the fact it is alway present to make the * push cursor, but use the fact it is always present to make the
* list deletion simple. * list deletion simple.
*/ */
void void

View file

@ -22,7 +22,7 @@
#include "xfs_inum.h" #include "xfs_inum.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_trans_priv.h" #include "xfs_trans_priv.h"
/* XXX: from here down needed until struct xfs_trans has it's own ailp */ /* XXX: from here down needed until struct xfs_trans has its own ailp */
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_buf_item.h" #include "xfs_buf_item.h"
#include "xfs_sb.h" #include "xfs_sb.h"

View file

@ -47,7 +47,7 @@
#define XFS_DIRREMOVE_SPACE_RES(mp) \ #define XFS_DIRREMOVE_SPACE_RES(mp) \
XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
#define XFS_IALLOC_SPACE_RES(mp) \ #define XFS_IALLOC_SPACE_RES(mp) \
(XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp)-1) (XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels - 1)
/* /*
* Space reservation values for various transactions. * Space reservation values for various transactions.

View file

@ -20,14 +20,6 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
/*
* POSIX Extensions
*/
typedef unsigned char uchar_t;
typedef unsigned short ushort_t;
typedef unsigned int uint_t;
typedef unsigned long ulong_t;
/* /*
* Additional type declarations for XFS * Additional type declarations for XFS
*/ */

View file

@ -374,7 +374,7 @@ xfs_truncate_file(
/* /*
* Follow the normal truncate locking protocol. Since we * Follow the normal truncate locking protocol. Since we
* hold the inode in the transaction, we know that it's number * hold the inode in the transaction, we know that its number
* of references will stay constant. * of references will stay constant.
*/ */
xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_ilock(ip, XFS_ILOCK_EXCL);

View file

@ -1136,7 +1136,7 @@ xfs_inactive(
* If the inode is already free, then there can be nothing * If the inode is already free, then there can be nothing
* to clean up here. * to clean up here.
*/ */
if (ip->i_d.di_mode == 0 || VN_BAD(VFS_I(ip))) { if (ip->i_d.di_mode == 0 || is_bad_inode(VFS_I(ip))) {
ASSERT(ip->i_df.if_real_bytes == 0); ASSERT(ip->i_df.if_real_bytes == 0);
ASSERT(ip->i_df.if_broot_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0);
return VN_INACTIVE_CACHE; return VN_INACTIVE_CACHE;
@ -1387,23 +1387,28 @@ xfs_create(
xfs_inode_t **ipp, xfs_inode_t **ipp,
cred_t *credp) cred_t *credp)
{ {
xfs_mount_t *mp = dp->i_mount; int is_dir = S_ISDIR(mode);
xfs_inode_t *ip; struct xfs_mount *mp = dp->i_mount;
xfs_trans_t *tp; struct xfs_inode *ip = NULL;
struct xfs_trans *tp = NULL;
int error; int error;
xfs_bmap_free_t free_list; xfs_bmap_free_t free_list;
xfs_fsblock_t first_block; xfs_fsblock_t first_block;
boolean_t unlock_dp_on_error = B_FALSE; boolean_t unlock_dp_on_error = B_FALSE;
int dm_event_sent = 0;
uint cancel_flags; uint cancel_flags;
int committed; int committed;
xfs_prid_t prid; xfs_prid_t prid;
struct xfs_dquot *udqp, *gdqp; struct xfs_dquot *udqp = NULL;
struct xfs_dquot *gdqp = NULL;
uint resblks; uint resblks;
uint log_res;
uint log_count;
ASSERT(!*ipp);
xfs_itrace_entry(dp); xfs_itrace_entry(dp);
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) { if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
dp, DM_RIGHT_NULL, NULL, dp, DM_RIGHT_NULL, NULL,
@ -1412,84 +1417,97 @@ xfs_create(
if (error) if (error)
return error; return error;
dm_event_sent = 1;
} }
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
/* Return through std_return after this point. */
udqp = gdqp = NULL;
if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
prid = dp->i_d.di_projid; prid = dp->i_d.di_projid;
else else
prid = (xfs_prid_t)dfltprid; prid = dfltprid;
/* /*
* Make sure that we have allocated dquot(s) on disk. * Make sure that we have allocated dquot(s) on disk.
*/ */
error = XFS_QM_DQVOPALLOC(mp, dp, error = XFS_QM_DQVOPALLOC(mp, dp,
current_fsuid(), current_fsgid(), prid, current_fsuid(), current_fsgid(), prid,
XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error) if (error)
goto std_return; goto std_return;
ip = NULL; if (is_dir) {
rdev = 0;
resblks = XFS_MKDIR_SPACE_RES(mp, name->len);
log_res = XFS_MKDIR_LOG_RES(mp);
log_count = XFS_MKDIR_LOG_COUNT;
tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
} else {
resblks = XFS_CREATE_SPACE_RES(mp, name->len);
log_res = XFS_CREATE_LOG_RES(mp);
log_count = XFS_CREATE_LOG_COUNT;
tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
}
tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
cancel_flags = XFS_TRANS_RELEASE_LOG_RES; cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
resblks = XFS_CREATE_SPACE_RES(mp, name->len);
/* /*
* Initially assume that the file does not exist and * Initially assume that the file does not exist and
* reserve the resources for that case. If that is not * reserve the resources for that case. If that is not
* the case we'll drop the one we have and get a more * the case we'll drop the one we have and get a more
* appropriate transaction later. * appropriate transaction later.
*/ */
error = xfs_trans_reserve(tp, resblks, XFS_CREATE_LOG_RES(mp), 0, error = xfs_trans_reserve(tp, resblks, log_res, 0,
XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT); XFS_TRANS_PERM_LOG_RES, log_count);
if (error == ENOSPC) { if (error == ENOSPC) {
resblks = 0; resblks = 0;
error = xfs_trans_reserve(tp, 0, XFS_CREATE_LOG_RES(mp), 0, error = xfs_trans_reserve(tp, 0, log_res, 0,
XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT); XFS_TRANS_PERM_LOG_RES, log_count);
} }
if (error) { if (error) {
cancel_flags = 0; cancel_flags = 0;
goto error_return; goto out_trans_cancel;
} }
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
unlock_dp_on_error = B_TRUE; unlock_dp_on_error = B_TRUE;
xfs_bmap_init(&free_list, &first_block); /*
* Check for directory link count overflow.
*/
if (is_dir && dp->i_d.di_nlink >= XFS_MAXLINK) {
error = XFS_ERROR(EMLINK);
goto out_trans_cancel;
}
ASSERT(ip == NULL); xfs_bmap_init(&free_list, &first_block);
/* /*
* Reserve disk quota and the inode. * Reserve disk quota and the inode.
*/ */
error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0); error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0);
if (error) if (error)
goto error_return; goto out_trans_cancel;
error = xfs_dir_canenter(tp, dp, name, resblks); error = xfs_dir_canenter(tp, dp, name, resblks);
if (error) if (error)
goto error_return; goto out_trans_cancel;
error = xfs_dir_ialloc(&tp, dp, mode, 1,
rdev, credp, prid, resblks > 0, /*
&ip, &committed); * A newly created regular or special file just has one directory
* entry pointing to them, but a directory also the "." entry
* pointing to itself.
*/
error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, credp,
prid, resblks > 0, &ip, &committed);
if (error) { if (error) {
if (error == ENOSPC) if (error == ENOSPC)
goto error_return; goto out_trans_cancel;
goto abort_return; goto out_trans_abort;
} }
xfs_itrace_ref(ip);
/* /*
* At this point, we've gotten a newly allocated inode. * At this point, we've gotten a newly allocated inode.
* It is locked (and joined to the transaction). * It is locked (and joined to the transaction).
*/ */
xfs_itrace_ref(ip);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
/* /*
@ -1508,19 +1526,28 @@ xfs_create(
resblks - XFS_IALLOC_SPACE_RES(mp) : 0); resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
if (error) { if (error) {
ASSERT(error != ENOSPC); ASSERT(error != ENOSPC);
goto abort_return; goto out_trans_abort;
} }
xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
if (is_dir) {
error = xfs_dir_init(tp, ip, dp);
if (error)
goto out_bmap_cancel;
error = xfs_bumplink(tp, dp);
if (error)
goto out_bmap_cancel;
}
/* /*
* If this is a synchronous mount, make sure that the * If this is a synchronous mount, make sure that the
* create transaction goes to disk before returning to * create transaction goes to disk before returning to
* the user. * the user.
*/ */
if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) { if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
xfs_trans_set_sync(tp); xfs_trans_set_sync(tp);
}
/* /*
* Attach the dquot(s) to the inodes and modify them incore. * Attach the dquot(s) to the inodes and modify them incore.
@ -1537,16 +1564,13 @@ xfs_create(
IHOLD(ip); IHOLD(ip);
error = xfs_bmap_finish(&tp, &free_list, &committed); error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) { if (error)
xfs_bmap_cancel(&free_list); goto out_abort_rele;
goto abort_rele;
}
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
if (error) { if (error) {
IRELE(ip); IRELE(ip);
tp = NULL; goto out_dqrele;
goto error_return;
} }
XFS_QM_DQRELE(mp, udqp); XFS_QM_DQRELE(mp, udqp);
@ -1555,26 +1579,22 @@ xfs_create(
*ipp = ip; *ipp = ip;
/* Fallthrough to std_return with error = 0 */ /* Fallthrough to std_return with error = 0 */
std_return:
std_return: if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
if ((*ipp || (error != 0 && dm_event_sent != 0)) && XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, dp, DM_RIGHT_NULL,
DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) { ip, DM_RIGHT_NULL, name->name, NULL, mode,
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, error, 0);
dp, DM_RIGHT_NULL,
*ipp ? ip : NULL,
DM_RIGHT_NULL, name->name, NULL,
mode, error, 0);
} }
return error; return error;
abort_return: out_bmap_cancel:
xfs_bmap_cancel(&free_list);
out_trans_abort:
cancel_flags |= XFS_TRANS_ABORT; cancel_flags |= XFS_TRANS_ABORT;
/* FALLTHROUGH */ out_trans_cancel:
xfs_trans_cancel(tp, cancel_flags);
error_return: out_dqrele:
if (tp != NULL)
xfs_trans_cancel(tp, cancel_flags);
XFS_QM_DQRELE(mp, udqp); XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp); XFS_QM_DQRELE(mp, gdqp);
@ -1583,20 +1603,18 @@ xfs_create(
goto std_return; goto std_return;
abort_rele: out_abort_rele:
/* /*
* Wait until after the current transaction is aborted to * Wait until after the current transaction is aborted to
* release the inode. This prevents recursive transactions * release the inode. This prevents recursive transactions
* and deadlocks from xfs_inactive. * and deadlocks from xfs_inactive.
*/ */
xfs_bmap_cancel(&free_list);
cancel_flags |= XFS_TRANS_ABORT; cancel_flags |= XFS_TRANS_ABORT;
xfs_trans_cancel(tp, cancel_flags); xfs_trans_cancel(tp, cancel_flags);
IRELE(ip); IRELE(ip);
unlock_dp_on_error = B_FALSE;
XFS_QM_DQRELE(mp, udqp); goto out_dqrele;
XFS_QM_DQRELE(mp, gdqp);
goto std_return;
} }
#ifdef DEBUG #ifdef DEBUG
@ -2004,8 +2022,10 @@ xfs_link(
/* Return through std_return after this point. */ /* Return through std_return after this point. */
error = XFS_QM_DQATTACH(mp, sip, 0); error = XFS_QM_DQATTACH(mp, sip, 0);
if (!error && sip != tdp) if (error)
error = XFS_QM_DQATTACH(mp, tdp, 0); goto std_return;
error = XFS_QM_DQATTACH(mp, tdp, 0);
if (error) if (error)
goto std_return; goto std_return;
@ -2110,209 +2130,6 @@ xfs_link(
goto std_return; goto std_return;
} }
int
xfs_mkdir(
xfs_inode_t *dp,
struct xfs_name *dir_name,
mode_t mode,
xfs_inode_t **ipp,
cred_t *credp)
{
xfs_mount_t *mp = dp->i_mount;
xfs_inode_t *cdp; /* inode of created dir */
xfs_trans_t *tp;
int cancel_flags;
int error;
int committed;
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
boolean_t unlock_dp_on_error = B_FALSE;
boolean_t created = B_FALSE;
int dm_event_sent = 0;
xfs_prid_t prid;
struct xfs_dquot *udqp, *gdqp;
uint resblks;
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
tp = NULL;
if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
dp, DM_RIGHT_NULL, NULL,
DM_RIGHT_NULL, dir_name->name, NULL,
mode, 0, 0);
if (error)
return error;
dm_event_sent = 1;
}
/* Return through std_return after this point. */
xfs_itrace_entry(dp);
mp = dp->i_mount;
udqp = gdqp = NULL;
if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
prid = dp->i_d.di_projid;
else
prid = (xfs_prid_t)dfltprid;
/*
* Make sure that we have allocated dquot(s) on disk.
*/
error = XFS_QM_DQVOPALLOC(mp, dp,
current_fsuid(), current_fsgid(), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error)
goto std_return;
tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
resblks = XFS_MKDIR_SPACE_RES(mp, dir_name->len);
error = xfs_trans_reserve(tp, resblks, XFS_MKDIR_LOG_RES(mp), 0,
XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT);
if (error == ENOSPC) {
resblks = 0;
error = xfs_trans_reserve(tp, 0, XFS_MKDIR_LOG_RES(mp), 0,
XFS_TRANS_PERM_LOG_RES,
XFS_MKDIR_LOG_COUNT);
}
if (error) {
cancel_flags = 0;
goto error_return;
}
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
unlock_dp_on_error = B_TRUE;
/*
* Check for directory link count overflow.
*/
if (dp->i_d.di_nlink >= XFS_MAXLINK) {
error = XFS_ERROR(EMLINK);
goto error_return;
}
/*
* Reserve disk quota and the inode.
*/
error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0);
if (error)
goto error_return;
error = xfs_dir_canenter(tp, dp, dir_name, resblks);
if (error)
goto error_return;
/*
* create the directory inode.
*/
error = xfs_dir_ialloc(&tp, dp, mode, 2,
0, credp, prid, resblks > 0,
&cdp, NULL);
if (error) {
if (error == ENOSPC)
goto error_return;
goto abort_return;
}
xfs_itrace_ref(cdp);
/*
* Now we add the directory inode to the transaction.
* We waited until now since xfs_dir_ialloc might start
* a new transaction. Had we joined the transaction
* earlier, the locks might have gotten released. An error
* from here on will result in the transaction cancel
* unlocking dp so don't do it explicitly in the error path.
*/
IHOLD(dp);
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
unlock_dp_on_error = B_FALSE;
xfs_bmap_init(&free_list, &first_block);
error = xfs_dir_createname(tp, dp, dir_name, cdp->i_ino,
&first_block, &free_list, resblks ?
resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
if (error) {
ASSERT(error != ENOSPC);
goto error1;
}
xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
error = xfs_dir_init(tp, cdp, dp);
if (error)
goto error2;
error = xfs_bumplink(tp, dp);
if (error)
goto error2;
created = B_TRUE;
*ipp = cdp;
IHOLD(cdp);
/*
* Attach the dquots to the new inode and modify the icount incore.
*/
XFS_QM_DQVOPCREATE(mp, tp, cdp, udqp, gdqp);
/*
* If this is a synchronous mount, make sure that the
* mkdir transaction goes to disk before returning to
* the user.
*/
if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
IRELE(cdp);
goto error2;
}
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp);
if (error) {
IRELE(cdp);
}
/* Fall through to std_return with error = 0 or errno from
* xfs_trans_commit. */
std_return:
if ((created || (error != 0 && dm_event_sent != 0)) &&
DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
dp, DM_RIGHT_NULL,
created ? cdp : NULL,
DM_RIGHT_NULL,
dir_name->name, NULL,
mode, error, 0);
}
return error;
error2:
error1:
xfs_bmap_cancel(&free_list);
abort_return:
cancel_flags |= XFS_TRANS_ABORT;
error_return:
xfs_trans_cancel(tp, cancel_flags);
XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp);
if (unlock_dp_on_error)
xfs_iunlock(dp, XFS_ILOCK_EXCL);
goto std_return;
}
int int
xfs_symlink( xfs_symlink(
xfs_inode_t *dp, xfs_inode_t *dp,
@ -2586,51 +2403,6 @@ xfs_symlink(
goto std_return; goto std_return;
} }
int
xfs_inode_flush(
xfs_inode_t *ip,
int flags)
{
xfs_mount_t *mp = ip->i_mount;
int error = 0;
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
/*
* Bypass inodes which have already been cleaned by
* the inode flush clustering code inside xfs_iflush
*/
if (xfs_inode_clean(ip))
return 0;
/*
* We make this non-blocking if the inode is contended,
* return EAGAIN to indicate to the caller that they
* did not succeed. This prevents the flush path from
* blocking on inodes inside another operation right
* now, they get caught later by xfs_sync.
*/
if (flags & FLUSH_SYNC) {
xfs_ilock(ip, XFS_ILOCK_SHARED);
xfs_iflock(ip);
} else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) {
xfs_iunlock(ip, XFS_ILOCK_SHARED);
return EAGAIN;
}
} else {
return EAGAIN;
}
error = xfs_iflush(ip, (flags & FLUSH_SYNC) ? XFS_IFLUSH_SYNC
: XFS_IFLUSH_ASYNC_NOBLOCK);
xfs_iunlock(ip, XFS_ILOCK_SHARED);
return error;
}
int int
xfs_set_dmattrs( xfs_set_dmattrs(
xfs_inode_t *ip, xfs_inode_t *ip,
@ -2676,7 +2448,7 @@ xfs_reclaim(
ASSERT(!VN_MAPPED(VFS_I(ip))); ASSERT(!VN_MAPPED(VFS_I(ip)));
/* bad inode, get out here ASAP */ /* bad inode, get out here ASAP */
if (VN_BAD(VFS_I(ip))) { if (is_bad_inode(VFS_I(ip))) {
xfs_ireclaim(ip); xfs_ireclaim(ip);
return 0; return 0;
} }
@ -3090,7 +2862,7 @@ xfs_free_file_space(
/* /*
* Need to zero the stuff we're not freeing, on disk. * Need to zero the stuff we're not freeing, on disk.
* If its a realtime file & can't use unwritten extents then we * If it's a realtime file & can't use unwritten extents then we
* actually need to zero the extent edges. Otherwise xfs_bunmapi * actually need to zero the extent edges. Otherwise xfs_bunmapi
* will take care of it for us. * will take care of it for us.
*/ */

View file

@ -31,14 +31,11 @@ int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
struct xfs_inode *ip); struct xfs_inode *ip);
int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
struct xfs_name *target_name); struct xfs_name *target_name);
int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
mode_t mode, struct xfs_inode **ipp, cred_t *credp);
int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize, int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize,
xfs_off_t *offset, filldir_t filldir); xfs_off_t *offset, filldir_t filldir);
int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
const char *target_path, mode_t mode, struct xfs_inode **ipp, const char *target_path, mode_t mode, struct xfs_inode **ipp,
cred_t *credp); cred_t *credp);
int xfs_inode_flush(struct xfs_inode *ip, int flags);
int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
int xfs_reclaim(struct xfs_inode *ip); int xfs_reclaim(struct xfs_inode *ip);
int xfs_change_file_space(struct xfs_inode *ip, int cmd, int xfs_change_file_space(struct xfs_inode *ip, int cmd,