ap->logbufsize);
return XFS_ERROR(EINVAL);
}
+ mp->m_ihsize = ap->ihashsize;
mp->m_logbsize = ap->logbufsize;
mp->m_fsname_len = strlen(ap->fsname) + 1;
mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
if (ap->flags & XFSMNT_NOUUID)
mp->m_flags |= XFS_MOUNT_NOUUID;
+ if (ap->flags & XFSMNT_TAGXID)
+ mp->m_flags |= XFS_MOUNT_TAGXID;
if (ap->flags & XFSMNT_NOLOGFLUSH)
mp->m_flags |= XFS_MOUNT_NOLOGFLUSH;
return XFS_ERROR(EINVAL);
}
+ if (ap->flags & XFSMNT_TAGXID)
+ vfs->vfs_super->s_flags |= MS_TAGXID;
return 0;
}
ddev = vfsp->vfs_super->s_bdev;
logdev = rtdev = NULL;
+ /*
+ * Setup xfs_mount function vectors from available behaviors
+ */
+ p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
+ mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
+ p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
+ mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
+ p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
+ mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+
/*
* Open real time and log devices - order is important.
*/
}
}
- /*
- * Setup xfs_mount function vectors from available behaviors
- */
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
- mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
- mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
- mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
-
/*
* Setup xfs_mount buffer target pointers
*/
- mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
- if (rtdev)
- mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev);
+ error = ENOMEM;
+ mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
+ if (!mp->m_ddev_targp) {
+ xfs_blkdev_put(logdev);
+ xfs_blkdev_put(rtdev);
+ return error;
+ }
+ if (rtdev) {
+ mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
+ if (!mp->m_rtdev_targp)
+ goto error0;
+ }
mp->m_logdev_targp = (logdev && logdev != ddev) ?
- xfs_alloc_buftarg(logdev) : mp->m_ddev_targp;
+ xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
+ if (!mp->m_logdev_targp)
+ goto error0;
/*
* Setup flags based on mount(2) options and then the superblock
*/
error = xfs_start_flags(vfsp, args, mp);
if (error)
- goto error;
+ goto error1;
error = xfs_readsb(mp);
if (error)
- goto error;
+ goto error1;
error = xfs_finish_flags(vfsp, args, mp);
- if (error) {
- xfs_freesb(mp);
- goto error;
- }
+ if (error)
+ goto error2;
/*
* Setup xfs_mount buffer target pointers based on superblock
*/
- xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
- mp->m_sb.sb_sectsize);
- if (logdev && logdev != ddev) {
+ error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
+ mp->m_sb.sb_sectsize);
+ if (!error && logdev && logdev != ddev) {
unsigned int log_sector_size = BBSIZE;
if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
log_sector_size = mp->m_sb.sb_logsectsize;
- xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize,
- log_sector_size);
+ error = xfs_setsize_buftarg(mp->m_logdev_targp,
+ mp->m_sb.sb_blocksize,
+ log_sector_size);
}
- if (rtdev)
- xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize,
- mp->m_sb.sb_blocksize);
+ if (!error && rtdev)
+ error = xfs_setsize_buftarg(mp->m_rtdev_targp,
+ mp->m_sb.sb_blocksize,
+ mp->m_sb.sb_sectsize);
+ if (error)
+ goto error2;
- if (!(error = XFS_IOINIT(vfsp, args, flags)))
+ error = XFS_IOINIT(vfsp, args, flags);
+ if (!error)
return 0;
-
- error:
+error2:
+ if (mp->m_sb_bp)
+ xfs_freesb(mp);
+error1:
xfs_binval(mp->m_ddev_targp);
- if (logdev != NULL && logdev != ddev) {
+ if (logdev && logdev != ddev)
xfs_binval(mp->m_logdev_targp);
- }
- if (rtdev != NULL) {
+ if (rtdev)
xfs_binval(mp->m_rtdev_targp);
- }
- xfs_unmountfs_close(mp, NULL);
+error0:
+ xfs_unmountfs_close(mp, credp);
return error;
}
continue;
}
+ if (VN_BAD(vp)) {
+ ip = ip->i_mnext;
+ continue;
+ }
+
if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
XFS_MOUNT_IUNLOCK(mp);
kmem_free(ipointer, sizeof(xfs_iptr_t));
}
/*
- * xfs_vget - called by DMAPI to get vnode from file handle
+ * xfs_vget - called by DMAPI and NFSD to get vnode from file handle
*/
STATIC int
xfs_vget(
vnode_t **vpp,
fid_t *fidp)
{
- xfs_fid_t *xfid;
+ xfs_mount_t *mp = XFS_BHVTOM(bdp);
+ xfs_fid_t *xfid = (struct xfs_fid *)fidp;
xfs_inode_t *ip;
int error;
xfs_ino_t ino;
unsigned int igen;
- xfs_mount_t *mp;
- xfid = (struct xfs_fid *)fidp;
- if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
- ino = xfid->xfs_fid_ino;
- igen = xfid->xfs_fid_gen;
- } else {
- /*
- * Invalid. Since handles can be created in user space
- * and passed in via gethandle(), this is not cause for
- * a panic.
- */
+ /*
+ * Invalid. Since handles can be created in user space and passed in
+ * via gethandle(), this is not cause for a panic.
+ */
+ if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))
return XFS_ERROR(EINVAL);
- }
- mp = XFS_BHVTOM(bdp);
- error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);
+
+ ino = xfid->xfs_fid_ino;
+ igen = xfid->xfs_fid_gen;
+
+ /*
+ * NFS can sometimes send requests for ino 0. Fail them gracefully.
+ */
+ if (ino == 0)
+ return XFS_ERROR(ESTALE);
+
+ error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
if (error) {
*vpp = NULL;
return error;
}
+
if (ip == NULL) {
*vpp = NULL;
return XFS_ERROR(EIO);
}
- if (ip->i_d.di_mode == 0 || (igen && (ip->i_d.di_gen != igen))) {
+ if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
xfs_iput_new(ip, XFS_ILOCK_SHARED);
*vpp = NULL;
return XFS_ERROR(ENOENT);
#define MNTOPT_SWIDTH "swidth" /* data volume stripe width */
#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */
#define MNTOPT_MTPT "mtpt" /* filesystem mount point */
+#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
#define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */
#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
#define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */
#define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */
#define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */
+#define MNTOPT_TAGXID "tagxid" /* context xid tagging for inodes */
int
iosize = simple_strtoul(value, &eov, 10);
args->flags |= XFSMNT_IOSIZE;
args->iosizelog = (uint8_t) iosize;
+ } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
+ if (!value || !*value) {
+ printk("XFS: %s option requires an argument\n",
+ this_char);
+ return EINVAL;
+ }
+ args->ihashsize = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
args->flags |= XFSMNT_WSYNC;
} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
args->flags &= ~XFSMNT_IDELETE;
} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
args->flags |= XFSMNT_IDELETE;
+ } else if (!strcmp(this_char, MNTOPT_TAGXID)) {
+ args->flags |= XFSMNT_TAGXID;
} else if (!strcmp(this_char, "osyncisdsync")) {
/* no-op, this is now the default */
printk("XFS: osyncisdsync is now the default, option is deprecated.\n");