|
@@ -75,26 +75,23 @@ xfs_open(
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * xfs_setattr
|
|
|
|
- */
|
|
|
|
int
|
|
int
|
|
xfs_setattr(
|
|
xfs_setattr(
|
|
- xfs_inode_t *ip,
|
|
|
|
- bhv_vattr_t *vap,
|
|
|
|
|
|
+ struct xfs_inode *ip,
|
|
|
|
+ struct iattr *iattr,
|
|
int flags,
|
|
int flags,
|
|
cred_t *credp)
|
|
cred_t *credp)
|
|
{
|
|
{
|
|
xfs_mount_t *mp = ip->i_mount;
|
|
xfs_mount_t *mp = ip->i_mount;
|
|
|
|
+ struct inode *inode = XFS_ITOV(ip);
|
|
|
|
+ int mask = iattr->ia_valid;
|
|
xfs_trans_t *tp;
|
|
xfs_trans_t *tp;
|
|
- int mask;
|
|
|
|
int code;
|
|
int code;
|
|
uint lock_flags;
|
|
uint lock_flags;
|
|
uint commit_flags=0;
|
|
uint commit_flags=0;
|
|
uid_t uid=0, iuid=0;
|
|
uid_t uid=0, iuid=0;
|
|
gid_t gid=0, igid=0;
|
|
gid_t gid=0, igid=0;
|
|
int timeflags = 0;
|
|
int timeflags = 0;
|
|
- xfs_prid_t projid=0, iprojid=0;
|
|
|
|
struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
|
|
struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
|
|
int file_owner;
|
|
int file_owner;
|
|
int need_iolock = 1;
|
|
int need_iolock = 1;
|
|
@@ -104,30 +101,9 @@ xfs_setattr(
|
|
if (mp->m_flags & XFS_MOUNT_RDONLY)
|
|
if (mp->m_flags & XFS_MOUNT_RDONLY)
|
|
return XFS_ERROR(EROFS);
|
|
return XFS_ERROR(EROFS);
|
|
|
|
|
|
- /*
|
|
|
|
- * Cannot set certain attributes.
|
|
|
|
- */
|
|
|
|
- mask = vap->va_mask;
|
|
|
|
- if (mask & XFS_AT_NOSET) {
|
|
|
|
- return XFS_ERROR(EINVAL);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
|
return XFS_ERROR(EIO);
|
|
return XFS_ERROR(EIO);
|
|
|
|
|
|
- /*
|
|
|
|
- * Timestamps do not need to be logged and hence do not
|
|
|
|
- * need to be done within a transaction.
|
|
|
|
- */
|
|
|
|
- if (mask & XFS_AT_UPDTIMES) {
|
|
|
|
- ASSERT((mask & ~XFS_AT_UPDTIMES) == 0);
|
|
|
|
- timeflags = ((mask & XFS_AT_UPDATIME) ? XFS_ICHGTIME_ACC : 0) |
|
|
|
|
- ((mask & XFS_AT_UPDCTIME) ? XFS_ICHGTIME_CHG : 0) |
|
|
|
|
- ((mask & XFS_AT_UPDMTIME) ? XFS_ICHGTIME_MOD : 0);
|
|
|
|
- xfs_ichgtime(ip, timeflags);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
olddquot1 = olddquot2 = NULL;
|
|
olddquot1 = olddquot2 = NULL;
|
|
udqp = gdqp = NULL;
|
|
udqp = gdqp = NULL;
|
|
|
|
|
|
@@ -139,28 +115,22 @@ xfs_setattr(
|
|
* If the IDs do change before we take the ilock, we're covered
|
|
* If the IDs do change before we take the ilock, we're covered
|
|
* because the i_*dquot fields will get updated anyway.
|
|
* because the i_*dquot fields will get updated anyway.
|
|
*/
|
|
*/
|
|
- if (XFS_IS_QUOTA_ON(mp) &&
|
|
|
|
- (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
|
|
|
|
|
|
+ if (XFS_IS_QUOTA_ON(mp) && (mask & (ATTR_UID|ATTR_GID))) {
|
|
uint qflags = 0;
|
|
uint qflags = 0;
|
|
|
|
|
|
- if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
|
|
|
|
- uid = vap->va_uid;
|
|
|
|
|
|
+ if ((mask & ATTR_UID) && XFS_IS_UQUOTA_ON(mp)) {
|
|
|
|
+ uid = iattr->ia_uid;
|
|
qflags |= XFS_QMOPT_UQUOTA;
|
|
qflags |= XFS_QMOPT_UQUOTA;
|
|
} else {
|
|
} else {
|
|
uid = ip->i_d.di_uid;
|
|
uid = ip->i_d.di_uid;
|
|
}
|
|
}
|
|
- if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
|
|
|
|
- gid = vap->va_gid;
|
|
|
|
|
|
+ if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp)) {
|
|
|
|
+ gid = iattr->ia_gid;
|
|
qflags |= XFS_QMOPT_GQUOTA;
|
|
qflags |= XFS_QMOPT_GQUOTA;
|
|
} else {
|
|
} else {
|
|
gid = ip->i_d.di_gid;
|
|
gid = ip->i_d.di_gid;
|
|
}
|
|
}
|
|
- if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
|
|
|
|
- projid = vap->va_projid;
|
|
|
|
- qflags |= XFS_QMOPT_PQUOTA;
|
|
|
|
- } else {
|
|
|
|
- projid = ip->i_d.di_projid;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* We take a reference when we initialize udqp and gdqp,
|
|
* We take a reference when we initialize udqp and gdqp,
|
|
* so it is important that we never blindly double trip on
|
|
* so it is important that we never blindly double trip on
|
|
@@ -168,8 +138,8 @@ xfs_setattr(
|
|
*/
|
|
*/
|
|
ASSERT(udqp == NULL);
|
|
ASSERT(udqp == NULL);
|
|
ASSERT(gdqp == NULL);
|
|
ASSERT(gdqp == NULL);
|
|
- code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
|
|
|
|
- &udqp, &gdqp);
|
|
|
|
|
|
+ code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, ip->i_d.di_projid,
|
|
|
|
+ qflags, &udqp, &gdqp);
|
|
if (code)
|
|
if (code)
|
|
return code;
|
|
return code;
|
|
}
|
|
}
|
|
@@ -180,10 +150,10 @@ xfs_setattr(
|
|
*/
|
|
*/
|
|
tp = NULL;
|
|
tp = NULL;
|
|
lock_flags = XFS_ILOCK_EXCL;
|
|
lock_flags = XFS_ILOCK_EXCL;
|
|
- if (flags & ATTR_NOLOCK)
|
|
|
|
|
|
+ if (flags & XFS_ATTR_NOLOCK)
|
|
need_iolock = 0;
|
|
need_iolock = 0;
|
|
- if (!(mask & XFS_AT_SIZE)) {
|
|
|
|
- if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) ||
|
|
|
|
|
|
+ if (!(mask & ATTR_SIZE)) {
|
|
|
|
+ if ((mask != (ATTR_CTIME|ATTR_ATIME|ATTR_MTIME)) ||
|
|
(mp->m_flags & XFS_MOUNT_WSYNC)) {
|
|
(mp->m_flags & XFS_MOUNT_WSYNC)) {
|
|
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
|
|
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
|
|
commit_flags = 0;
|
|
commit_flags = 0;
|
|
@@ -196,10 +166,10 @@ xfs_setattr(
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
|
|
if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
|
|
- !(flags & ATTR_DMI)) {
|
|
|
|
|
|
+ !(flags & XFS_ATTR_DMI)) {
|
|
int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
|
|
int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
|
|
code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, ip,
|
|
code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, ip,
|
|
- vap->va_size, 0, dmflags, NULL);
|
|
|
|
|
|
+ iattr->ia_size, 0, dmflags, NULL);
|
|
if (code) {
|
|
if (code) {
|
|
lock_flags = 0;
|
|
lock_flags = 0;
|
|
goto error_return;
|
|
goto error_return;
|
|
@@ -219,9 +189,7 @@ xfs_setattr(
|
|
* Only the owner or users with CAP_FOWNER
|
|
* Only the owner or users with CAP_FOWNER
|
|
* capability may do these things.
|
|
* capability may do these things.
|
|
*/
|
|
*/
|
|
- if (mask &
|
|
|
|
- (XFS_AT_MODE|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_UID|
|
|
|
|
- XFS_AT_GID|XFS_AT_PROJID)) {
|
|
|
|
|
|
+ if (mask & (ATTR_MODE|ATTR_UID|ATTR_GID)) {
|
|
/*
|
|
/*
|
|
* CAP_FOWNER overrides the following restrictions:
|
|
* CAP_FOWNER overrides the following restrictions:
|
|
*
|
|
*
|
|
@@ -245,21 +213,21 @@ xfs_setattr(
|
|
* IDs of the calling process shall match the group owner of
|
|
* IDs of the calling process shall match the group owner of
|
|
* the file when setting the set-group-ID bit on that file
|
|
* the file when setting the set-group-ID bit on that file
|
|
*/
|
|
*/
|
|
- if (mask & XFS_AT_MODE) {
|
|
|
|
|
|
+ if (mask & ATTR_MODE) {
|
|
mode_t m = 0;
|
|
mode_t m = 0;
|
|
|
|
|
|
- if ((vap->va_mode & S_ISUID) && !file_owner)
|
|
|
|
|
|
+ if ((iattr->ia_mode & S_ISUID) && !file_owner)
|
|
m |= S_ISUID;
|
|
m |= S_ISUID;
|
|
- if ((vap->va_mode & S_ISGID) &&
|
|
|
|
|
|
+ if ((iattr->ia_mode & S_ISGID) &&
|
|
!in_group_p((gid_t)ip->i_d.di_gid))
|
|
!in_group_p((gid_t)ip->i_d.di_gid))
|
|
m |= S_ISGID;
|
|
m |= S_ISGID;
|
|
#if 0
|
|
#if 0
|
|
/* Linux allows this, Irix doesn't. */
|
|
/* Linux allows this, Irix doesn't. */
|
|
- if ((vap->va_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode))
|
|
|
|
|
|
+ if ((iattr->ia_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode))
|
|
m |= S_ISVTX;
|
|
m |= S_ISVTX;
|
|
#endif
|
|
#endif
|
|
if (m && !capable(CAP_FSETID))
|
|
if (m && !capable(CAP_FSETID))
|
|
- vap->va_mode &= ~m;
|
|
|
|
|
|
+ iattr->ia_mode &= ~m;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -270,7 +238,7 @@ xfs_setattr(
|
|
* and can change the group id only to a group of which he
|
|
* and can change the group id only to a group of which he
|
|
* or she is a member.
|
|
* or she is a member.
|
|
*/
|
|
*/
|
|
- if (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID)) {
|
|
|
|
|
|
+ if (mask & (ATTR_UID|ATTR_GID)) {
|
|
/*
|
|
/*
|
|
* These IDs could have changed since we last looked at them.
|
|
* These IDs could have changed since we last looked at them.
|
|
* But, we're assured that if the ownership did change
|
|
* But, we're assured that if the ownership did change
|
|
@@ -278,12 +246,9 @@ xfs_setattr(
|
|
* would have changed also.
|
|
* would have changed also.
|
|
*/
|
|
*/
|
|
iuid = ip->i_d.di_uid;
|
|
iuid = ip->i_d.di_uid;
|
|
- iprojid = ip->i_d.di_projid;
|
|
|
|
igid = ip->i_d.di_gid;
|
|
igid = ip->i_d.di_gid;
|
|
- gid = (mask & XFS_AT_GID) ? vap->va_gid : igid;
|
|
|
|
- uid = (mask & XFS_AT_UID) ? vap->va_uid : iuid;
|
|
|
|
- projid = (mask & XFS_AT_PROJID) ? (xfs_prid_t)vap->va_projid :
|
|
|
|
- iprojid;
|
|
|
|
|
|
+ gid = (mask & ATTR_GID) ? iattr->ia_gid : igid;
|
|
|
|
+ uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid;
|
|
|
|
|
|
/*
|
|
/*
|
|
* CAP_CHOWN overrides the following restrictions:
|
|
* CAP_CHOWN overrides the following restrictions:
|
|
@@ -303,11 +268,10 @@ xfs_setattr(
|
|
goto error_return;
|
|
goto error_return;
|
|
}
|
|
}
|
|
/*
|
|
/*
|
|
- * Do a quota reservation only if uid/projid/gid is actually
|
|
|
|
|
|
+ * Do a quota reservation only if uid/gid is actually
|
|
* going to change.
|
|
* going to change.
|
|
*/
|
|
*/
|
|
if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
|
|
if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
|
|
- (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
|
|
|
|
(XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
|
|
(XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
|
|
ASSERT(tp);
|
|
ASSERT(tp);
|
|
code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
|
|
code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
|
|
@@ -321,13 +285,13 @@ xfs_setattr(
|
|
/*
|
|
/*
|
|
* Truncate file. Must have write permission and not be a directory.
|
|
* Truncate file. Must have write permission and not be a directory.
|
|
*/
|
|
*/
|
|
- if (mask & XFS_AT_SIZE) {
|
|
|
|
|
|
+ if (mask & ATTR_SIZE) {
|
|
/* Short circuit the truncate case for zero length files */
|
|
/* Short circuit the truncate case for zero length files */
|
|
- if ((vap->va_size == 0) &&
|
|
|
|
- (ip->i_size == 0) && (ip->i_d.di_nextents == 0)) {
|
|
|
|
|
|
+ if (iattr->ia_size == 0 &&
|
|
|
|
+ ip->i_size == 0 && ip->i_d.di_nextents == 0) {
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
lock_flags &= ~XFS_ILOCK_EXCL;
|
|
lock_flags &= ~XFS_ILOCK_EXCL;
|
|
- if (mask & XFS_AT_CTIME)
|
|
|
|
|
|
+ if (mask & ATTR_CTIME)
|
|
xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
|
xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
|
code = 0;
|
|
code = 0;
|
|
goto error_return;
|
|
goto error_return;
|
|
@@ -350,9 +314,9 @@ xfs_setattr(
|
|
/*
|
|
/*
|
|
* Change file access or modified times.
|
|
* Change file access or modified times.
|
|
*/
|
|
*/
|
|
- if (mask & (XFS_AT_ATIME|XFS_AT_MTIME)) {
|
|
|
|
|
|
+ if (mask & (ATTR_ATIME|ATTR_MTIME)) {
|
|
if (!file_owner) {
|
|
if (!file_owner) {
|
|
- if ((flags & ATTR_UTIME) &&
|
|
|
|
|
|
+ if ((mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)) &&
|
|
!capable(CAP_FOWNER)) {
|
|
!capable(CAP_FOWNER)) {
|
|
code = XFS_ERROR(EPERM);
|
|
code = XFS_ERROR(EPERM);
|
|
goto error_return;
|
|
goto error_return;
|
|
@@ -360,91 +324,24 @@ xfs_setattr(
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * Change extent size or realtime flag.
|
|
|
|
- */
|
|
|
|
- if (mask & (XFS_AT_EXTSIZE|XFS_AT_XFLAGS)) {
|
|
|
|
- /*
|
|
|
|
- * Can't change extent size if any extents are allocated.
|
|
|
|
- */
|
|
|
|
- if (ip->i_d.di_nextents && (mask & XFS_AT_EXTSIZE) &&
|
|
|
|
- ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
|
|
|
|
- vap->va_extsize) ) {
|
|
|
|
- code = XFS_ERROR(EINVAL); /* EFBIG? */
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Can't change realtime flag if any extents are allocated.
|
|
|
|
- */
|
|
|
|
- if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
|
|
|
|
- (mask & XFS_AT_XFLAGS) &&
|
|
|
|
- (XFS_IS_REALTIME_INODE(ip)) !=
|
|
|
|
- (vap->va_xflags & XFS_XFLAG_REALTIME)) {
|
|
|
|
- code = XFS_ERROR(EINVAL); /* EFBIG? */
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
- /*
|
|
|
|
- * Extent size must be a multiple of the appropriate block
|
|
|
|
- * size, if set at all.
|
|
|
|
- */
|
|
|
|
- if ((mask & XFS_AT_EXTSIZE) && vap->va_extsize != 0) {
|
|
|
|
- xfs_extlen_t size;
|
|
|
|
-
|
|
|
|
- if (XFS_IS_REALTIME_INODE(ip) ||
|
|
|
|
- ((mask & XFS_AT_XFLAGS) &&
|
|
|
|
- (vap->va_xflags & XFS_XFLAG_REALTIME))) {
|
|
|
|
- size = mp->m_sb.sb_rextsize <<
|
|
|
|
- mp->m_sb.sb_blocklog;
|
|
|
|
- } else {
|
|
|
|
- size = mp->m_sb.sb_blocksize;
|
|
|
|
- }
|
|
|
|
- if (vap->va_extsize % size) {
|
|
|
|
- code = XFS_ERROR(EINVAL);
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- /*
|
|
|
|
- * If realtime flag is set then must have realtime data.
|
|
|
|
- */
|
|
|
|
- if ((mask & XFS_AT_XFLAGS) &&
|
|
|
|
- (vap->va_xflags & XFS_XFLAG_REALTIME)) {
|
|
|
|
- if ((mp->m_sb.sb_rblocks == 0) ||
|
|
|
|
- (mp->m_sb.sb_rextsize == 0) ||
|
|
|
|
- (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
|
|
|
|
- code = XFS_ERROR(EINVAL);
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Can't modify an immutable/append-only file unless
|
|
|
|
- * we have appropriate permission.
|
|
|
|
- */
|
|
|
|
- if ((mask & XFS_AT_XFLAGS) &&
|
|
|
|
- (ip->i_d.di_flags &
|
|
|
|
- (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
|
|
|
|
- (vap->va_xflags &
|
|
|
|
- (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
|
|
|
|
- !capable(CAP_LINUX_IMMUTABLE)) {
|
|
|
|
- code = XFS_ERROR(EPERM);
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Now we can make the changes. Before we join the inode
|
|
* Now we can make the changes. Before we join the inode
|
|
- * to the transaction, if XFS_AT_SIZE is set then take care of
|
|
|
|
|
|
+ * to the transaction, if ATTR_SIZE is set then take care of
|
|
* the part of the truncation that must be done without the
|
|
* the part of the truncation that must be done without the
|
|
* inode lock. This needs to be done before joining the inode
|
|
* inode lock. This needs to be done before joining the inode
|
|
* to the transaction, because the inode cannot be unlocked
|
|
* to the transaction, because the inode cannot be unlocked
|
|
* once it is a part of the transaction.
|
|
* once it is a part of the transaction.
|
|
*/
|
|
*/
|
|
- if (mask & XFS_AT_SIZE) {
|
|
|
|
|
|
+ if (mask & ATTR_SIZE) {
|
|
code = 0;
|
|
code = 0;
|
|
- if ((vap->va_size > ip->i_size) &&
|
|
|
|
- (flags & ATTR_NOSIZETOK) == 0) {
|
|
|
|
- code = xfs_igrow_start(ip, vap->va_size, credp);
|
|
|
|
|
|
+ if (iattr->ia_size > ip->i_size) {
|
|
|
|
+ /*
|
|
|
|
+ * Do the first part of growing a file: zero any data
|
|
|
|
+ * in the last block that is beyond the old EOF. We
|
|
|
|
+ * need to do this before the inode is joined to the
|
|
|
|
+ * transaction to modify the i_size.
|
|
|
|
+ */
|
|
|
|
+ code = xfs_zero_eof(ip, iattr->ia_size, ip->i_size);
|
|
}
|
|
}
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
|
|
|
|
@@ -461,10 +358,10 @@ xfs_setattr(
|
|
* not within the range we care about here.
|
|
* not within the range we care about here.
|
|
*/
|
|
*/
|
|
if (!code &&
|
|
if (!code &&
|
|
- (ip->i_size != ip->i_d.di_size) &&
|
|
|
|
- (vap->va_size > ip->i_d.di_size)) {
|
|
|
|
|
|
+ ip->i_size != ip->i_d.di_size &&
|
|
|
|
+ iattr->ia_size > ip->i_d.di_size) {
|
|
code = xfs_flush_pages(ip,
|
|
code = xfs_flush_pages(ip,
|
|
- ip->i_d.di_size, vap->va_size,
|
|
|
|
|
|
+ ip->i_d.di_size, iattr->ia_size,
|
|
XFS_B_ASYNC, FI_NONE);
|
|
XFS_B_ASYNC, FI_NONE);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -472,7 +369,7 @@ xfs_setattr(
|
|
vn_iowait(ip);
|
|
vn_iowait(ip);
|
|
|
|
|
|
if (!code)
|
|
if (!code)
|
|
- code = xfs_itruncate_data(ip, vap->va_size);
|
|
|
|
|
|
+ code = xfs_itruncate_data(ip, iattr->ia_size);
|
|
if (code) {
|
|
if (code) {
|
|
ASSERT(tp == NULL);
|
|
ASSERT(tp == NULL);
|
|
lock_flags &= ~XFS_ILOCK_EXCL;
|
|
lock_flags &= ~XFS_ILOCK_EXCL;
|
|
@@ -501,28 +398,30 @@ xfs_setattr(
|
|
/*
|
|
/*
|
|
* Truncate file. Must have write permission and not be a directory.
|
|
* Truncate file. Must have write permission and not be a directory.
|
|
*/
|
|
*/
|
|
- if (mask & XFS_AT_SIZE) {
|
|
|
|
|
|
+ if (mask & ATTR_SIZE) {
|
|
/*
|
|
/*
|
|
* Only change the c/mtime if we are changing the size
|
|
* Only change the c/mtime if we are changing the size
|
|
* or we are explicitly asked to change it. This handles
|
|
* or we are explicitly asked to change it. This handles
|
|
* the semantic difference between truncate() and ftruncate()
|
|
* the semantic difference between truncate() and ftruncate()
|
|
* as implemented in the VFS.
|
|
* as implemented in the VFS.
|
|
*/
|
|
*/
|
|
- if (vap->va_size != ip->i_size || (mask & XFS_AT_CTIME))
|
|
|
|
|
|
+ if (iattr->ia_size != ip->i_size || (mask & ATTR_CTIME))
|
|
timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
|
|
timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
|
|
|
|
|
|
- if (vap->va_size > ip->i_size) {
|
|
|
|
- xfs_igrow_finish(tp, ip, vap->va_size,
|
|
|
|
- !(flags & ATTR_DMI));
|
|
|
|
- } else if ((vap->va_size <= ip->i_size) ||
|
|
|
|
- ((vap->va_size == 0) && ip->i_d.di_nextents)) {
|
|
|
|
|
|
+ if (iattr->ia_size > ip->i_size) {
|
|
|
|
+ ip->i_d.di_size = iattr->ia_size;
|
|
|
|
+ ip->i_size = iattr->ia_size;
|
|
|
|
+ if (!(flags & XFS_ATTR_DMI))
|
|
|
|
+ xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
|
|
|
|
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
|
|
|
+ } else if (iattr->ia_size <= ip->i_size ||
|
|
|
|
+ (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
|
|
/*
|
|
/*
|
|
* signal a sync transaction unless
|
|
* signal a sync transaction unless
|
|
* we're truncating an already unlinked
|
|
* we're truncating an already unlinked
|
|
* file on a wsync filesystem
|
|
* file on a wsync filesystem
|
|
*/
|
|
*/
|
|
- code = xfs_itruncate_finish(&tp, ip,
|
|
|
|
- (xfs_fsize_t)vap->va_size,
|
|
|
|
|
|
+ code = xfs_itruncate_finish(&tp, ip, iattr->ia_size,
|
|
XFS_DATA_FORK,
|
|
XFS_DATA_FORK,
|
|
((ip->i_d.di_nlink != 0 ||
|
|
((ip->i_d.di_nlink != 0 ||
|
|
!(mp->m_flags & XFS_MOUNT_WSYNC))
|
|
!(mp->m_flags & XFS_MOUNT_WSYNC))
|
|
@@ -544,9 +443,12 @@ xfs_setattr(
|
|
/*
|
|
/*
|
|
* Change file access modes.
|
|
* Change file access modes.
|
|
*/
|
|
*/
|
|
- if (mask & XFS_AT_MODE) {
|
|
|
|
|
|
+ if (mask & ATTR_MODE) {
|
|
ip->i_d.di_mode &= S_IFMT;
|
|
ip->i_d.di_mode &= S_IFMT;
|
|
- ip->i_d.di_mode |= vap->va_mode & ~S_IFMT;
|
|
|
|
|
|
+ ip->i_d.di_mode |= iattr->ia_mode & ~S_IFMT;
|
|
|
|
+
|
|
|
|
+ inode->i_mode &= S_IFMT;
|
|
|
|
+ inode->i_mode |= iattr->ia_mode & ~S_IFMT;
|
|
|
|
|
|
xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
|
|
xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
|
|
timeflags |= XFS_ICHGTIME_CHG;
|
|
timeflags |= XFS_ICHGTIME_CHG;
|
|
@@ -559,7 +461,7 @@ xfs_setattr(
|
|
* and can change the group id only to a group of which he
|
|
* and can change the group id only to a group of which he
|
|
* or she is a member.
|
|
* or she is a member.
|
|
*/
|
|
*/
|
|
- if (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID)) {
|
|
|
|
|
|
+ if (mask & (ATTR_UID|ATTR_GID)) {
|
|
/*
|
|
/*
|
|
* CAP_FSETID overrides the following restrictions:
|
|
* CAP_FSETID overrides the following restrictions:
|
|
*
|
|
*
|
|
@@ -577,39 +479,24 @@ xfs_setattr(
|
|
*/
|
|
*/
|
|
if (iuid != uid) {
|
|
if (iuid != uid) {
|
|
if (XFS_IS_UQUOTA_ON(mp)) {
|
|
if (XFS_IS_UQUOTA_ON(mp)) {
|
|
- ASSERT(mask & XFS_AT_UID);
|
|
|
|
|
|
+ ASSERT(mask & ATTR_UID);
|
|
ASSERT(udqp);
|
|
ASSERT(udqp);
|
|
olddquot1 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
|
|
olddquot1 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
|
|
&ip->i_udquot, udqp);
|
|
&ip->i_udquot, udqp);
|
|
}
|
|
}
|
|
ip->i_d.di_uid = uid;
|
|
ip->i_d.di_uid = uid;
|
|
|
|
+ inode->i_uid = uid;
|
|
}
|
|
}
|
|
if (igid != gid) {
|
|
if (igid != gid) {
|
|
if (XFS_IS_GQUOTA_ON(mp)) {
|
|
if (XFS_IS_GQUOTA_ON(mp)) {
|
|
ASSERT(!XFS_IS_PQUOTA_ON(mp));
|
|
ASSERT(!XFS_IS_PQUOTA_ON(mp));
|
|
- ASSERT(mask & XFS_AT_GID);
|
|
|
|
|
|
+ ASSERT(mask & ATTR_GID);
|
|
ASSERT(gdqp);
|
|
ASSERT(gdqp);
|
|
olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
|
|
olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
|
|
&ip->i_gdquot, gdqp);
|
|
&ip->i_gdquot, gdqp);
|
|
}
|
|
}
|
|
ip->i_d.di_gid = gid;
|
|
ip->i_d.di_gid = gid;
|
|
- }
|
|
|
|
- if (iprojid != projid) {
|
|
|
|
- if (XFS_IS_PQUOTA_ON(mp)) {
|
|
|
|
- ASSERT(!XFS_IS_GQUOTA_ON(mp));
|
|
|
|
- ASSERT(mask & XFS_AT_PROJID);
|
|
|
|
- ASSERT(gdqp);
|
|
|
|
- olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
|
|
|
|
- &ip->i_gdquot, gdqp);
|
|
|
|
- }
|
|
|
|
- ip->i_d.di_projid = projid;
|
|
|
|
- /*
|
|
|
|
- * We may have to rev the inode as well as
|
|
|
|
- * the superblock version number since projids didn't
|
|
|
|
- * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
|
|
|
|
- */
|
|
|
|
- if (ip->i_d.di_version == XFS_DINODE_VERSION_1)
|
|
|
|
- xfs_bump_ino_vers2(tp, ip);
|
|
|
|
|
|
+ inode->i_gid = gid;
|
|
}
|
|
}
|
|
|
|
|
|
xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
|
|
xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
|
|
@@ -620,82 +507,34 @@ xfs_setattr(
|
|
/*
|
|
/*
|
|
* Change file access or modified times.
|
|
* Change file access or modified times.
|
|
*/
|
|
*/
|
|
- if (mask & (XFS_AT_ATIME|XFS_AT_MTIME)) {
|
|
|
|
- if (mask & XFS_AT_ATIME) {
|
|
|
|
- ip->i_d.di_atime.t_sec = vap->va_atime.tv_sec;
|
|
|
|
- ip->i_d.di_atime.t_nsec = vap->va_atime.tv_nsec;
|
|
|
|
|
|
+ if (mask & (ATTR_ATIME|ATTR_MTIME)) {
|
|
|
|
+ if (mask & ATTR_ATIME) {
|
|
|
|
+ inode->i_atime = iattr->ia_atime;
|
|
|
|
+ ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
|
|
|
|
+ ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
|
|
ip->i_update_core = 1;
|
|
ip->i_update_core = 1;
|
|
timeflags &= ~XFS_ICHGTIME_ACC;
|
|
timeflags &= ~XFS_ICHGTIME_ACC;
|
|
}
|
|
}
|
|
- if (mask & XFS_AT_MTIME) {
|
|
|
|
- ip->i_d.di_mtime.t_sec = vap->va_mtime.tv_sec;
|
|
|
|
- ip->i_d.di_mtime.t_nsec = vap->va_mtime.tv_nsec;
|
|
|
|
|
|
+ if (mask & ATTR_MTIME) {
|
|
|
|
+ inode->i_mtime = iattr->ia_mtime;
|
|
|
|
+ ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
|
|
|
|
+ ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
|
|
timeflags &= ~XFS_ICHGTIME_MOD;
|
|
timeflags &= ~XFS_ICHGTIME_MOD;
|
|
timeflags |= XFS_ICHGTIME_CHG;
|
|
timeflags |= XFS_ICHGTIME_CHG;
|
|
}
|
|
}
|
|
- if (tp && (flags & ATTR_UTIME))
|
|
|
|
|
|
+ if (tp && (mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)))
|
|
xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
|
|
xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Change XFS-added attributes.
|
|
|
|
- */
|
|
|
|
- if (mask & (XFS_AT_EXTSIZE|XFS_AT_XFLAGS)) {
|
|
|
|
- if (mask & XFS_AT_EXTSIZE) {
|
|
|
|
- /*
|
|
|
|
- * Converting bytes to fs blocks.
|
|
|
|
- */
|
|
|
|
- ip->i_d.di_extsize = vap->va_extsize >>
|
|
|
|
- mp->m_sb.sb_blocklog;
|
|
|
|
- }
|
|
|
|
- if (mask & XFS_AT_XFLAGS) {
|
|
|
|
- uint di_flags;
|
|
|
|
-
|
|
|
|
- /* can't set PREALLOC this way, just preserve it */
|
|
|
|
- di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
|
|
|
|
- di_flags |= XFS_DIFLAG_IMMUTABLE;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_APPEND)
|
|
|
|
- di_flags |= XFS_DIFLAG_APPEND;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_SYNC)
|
|
|
|
- di_flags |= XFS_DIFLAG_SYNC;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_NOATIME)
|
|
|
|
- di_flags |= XFS_DIFLAG_NOATIME;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_NODUMP)
|
|
|
|
- di_flags |= XFS_DIFLAG_NODUMP;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
|
|
|
|
- di_flags |= XFS_DIFLAG_PROJINHERIT;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
|
|
|
|
- di_flags |= XFS_DIFLAG_NODEFRAG;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_FILESTREAM)
|
|
|
|
- di_flags |= XFS_DIFLAG_FILESTREAM;
|
|
|
|
- if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
|
|
|
|
- di_flags |= XFS_DIFLAG_RTINHERIT;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
|
|
|
|
- di_flags |= XFS_DIFLAG_NOSYMLINKS;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
|
|
|
|
- di_flags |= XFS_DIFLAG_EXTSZINHERIT;
|
|
|
|
- } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_REALTIME)
|
|
|
|
- di_flags |= XFS_DIFLAG_REALTIME;
|
|
|
|
- if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
|
|
|
|
- di_flags |= XFS_DIFLAG_EXTSIZE;
|
|
|
|
- }
|
|
|
|
- ip->i_d.di_flags = di_flags;
|
|
|
|
- }
|
|
|
|
- xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
|
|
|
- timeflags |= XFS_ICHGTIME_CHG;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Change file inode change time only if XFS_AT_CTIME set
|
|
|
|
|
|
+ * Change file inode change time only if ATTR_CTIME set
|
|
* AND we have been called by a DMI function.
|
|
* AND we have been called by a DMI function.
|
|
*/
|
|
*/
|
|
|
|
|
|
- if ( (flags & ATTR_DMI) && (mask & XFS_AT_CTIME) ) {
|
|
|
|
- ip->i_d.di_ctime.t_sec = vap->va_ctime.tv_sec;
|
|
|
|
- ip->i_d.di_ctime.t_nsec = vap->va_ctime.tv_nsec;
|
|
|
|
|
|
+ if ((flags & XFS_ATTR_DMI) && (mask & ATTR_CTIME)) {
|
|
|
|
+ inode->i_ctime = iattr->ia_ctime;
|
|
|
|
+ ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
|
|
|
|
+ ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
|
|
ip->i_update_core = 1;
|
|
ip->i_update_core = 1;
|
|
timeflags &= ~XFS_ICHGTIME_CHG;
|
|
timeflags &= ~XFS_ICHGTIME_CHG;
|
|
}
|
|
}
|
|
@@ -704,7 +543,7 @@ xfs_setattr(
|
|
* Send out timestamp changes that need to be set to the
|
|
* Send out timestamp changes that need to be set to the
|
|
* current time. Not done when called by a DMI function.
|
|
* current time. Not done when called by a DMI function.
|
|
*/
|
|
*/
|
|
- if (timeflags && !(flags & ATTR_DMI))
|
|
|
|
|
|
+ if (timeflags && !(flags & XFS_ATTR_DMI))
|
|
xfs_ichgtime(ip, timeflags);
|
|
xfs_ichgtime(ip, timeflags);
|
|
|
|
|
|
XFS_STATS_INC(xs_ig_attrchg);
|
|
XFS_STATS_INC(xs_ig_attrchg);
|
|
@@ -742,7 +581,7 @@ xfs_setattr(
|
|
}
|
|
}
|
|
|
|
|
|
if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
|
|
if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
|
|
- !(flags & ATTR_DMI)) {
|
|
|
|
|
|
+ !(flags & XFS_ATTR_DMI)) {
|
|
(void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL,
|
|
(void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL,
|
|
NULL, DM_RIGHT_NULL, NULL, NULL,
|
|
NULL, DM_RIGHT_NULL, NULL, NULL,
|
|
0, 0, AT_DELAY_FLAG(flags));
|
|
0, 0, AT_DELAY_FLAG(flags));
|
|
@@ -1601,12 +1440,18 @@ xfs_inactive(
|
|
return VN_INACTIVE_CACHE;
|
|
return VN_INACTIVE_CACHE;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
|
|
+/*
|
|
|
|
+ * Lookups up an inode from "name". If ci_name is not NULL, then a CI match
|
|
|
|
+ * is allowed, otherwise it has to be an exact match. If a CI match is found,
|
|
|
|
+ * ci_name->name will point to a the actual name (caller must free) or
|
|
|
|
+ * will be set to NULL if an exact match is found.
|
|
|
|
+ */
|
|
int
|
|
int
|
|
xfs_lookup(
|
|
xfs_lookup(
|
|
xfs_inode_t *dp,
|
|
xfs_inode_t *dp,
|
|
struct xfs_name *name,
|
|
struct xfs_name *name,
|
|
- xfs_inode_t **ipp)
|
|
|
|
|
|
+ xfs_inode_t **ipp,
|
|
|
|
+ struct xfs_name *ci_name)
|
|
{
|
|
{
|
|
xfs_ino_t inum;
|
|
xfs_ino_t inum;
|
|
int error;
|
|
int error;
|
|
@@ -1618,7 +1463,7 @@ xfs_lookup(
|
|
return XFS_ERROR(EIO);
|
|
return XFS_ERROR(EIO);
|
|
|
|
|
|
lock_mode = xfs_ilock_map_shared(dp);
|
|
lock_mode = xfs_ilock_map_shared(dp);
|
|
- error = xfs_dir_lookup(NULL, dp, name, &inum);
|
|
|
|
|
|
+ error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name);
|
|
xfs_iunlock_map_shared(dp, lock_mode);
|
|
xfs_iunlock_map_shared(dp, lock_mode);
|
|
|
|
|
|
if (error)
|
|
if (error)
|
|
@@ -1626,12 +1471,15 @@ xfs_lookup(
|
|
|
|
|
|
error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
|
|
error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
|
|
if (error)
|
|
if (error)
|
|
- goto out;
|
|
|
|
|
|
+ goto out_free_name;
|
|
|
|
|
|
xfs_itrace_ref(*ipp);
|
|
xfs_itrace_ref(*ipp);
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- out:
|
|
|
|
|
|
+out_free_name:
|
|
|
|
+ if (ci_name)
|
|
|
|
+ kmem_free(ci_name->name);
|
|
|
|
+out:
|
|
*ipp = NULL;
|
|
*ipp = NULL;
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
@@ -2098,13 +1946,6 @@ again:
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef DEBUG
|
|
|
|
-#define REMOVE_DEBUG_TRACE(x) {remove_which_error_return = (x);}
|
|
|
|
-int remove_which_error_return = 0;
|
|
|
|
-#else /* ! DEBUG */
|
|
|
|
-#define REMOVE_DEBUG_TRACE(x)
|
|
|
|
-#endif /* ! DEBUG */
|
|
|
|
-
|
|
|
|
int
|
|
int
|
|
xfs_remove(
|
|
xfs_remove(
|
|
xfs_inode_t *dp,
|
|
xfs_inode_t *dp,
|
|
@@ -2113,6 +1954,7 @@ xfs_remove(
|
|
{
|
|
{
|
|
xfs_mount_t *mp = dp->i_mount;
|
|
xfs_mount_t *mp = dp->i_mount;
|
|
xfs_trans_t *tp = NULL;
|
|
xfs_trans_t *tp = NULL;
|
|
|
|
+ int is_dir = S_ISDIR(ip->i_d.di_mode);
|
|
int error = 0;
|
|
int error = 0;
|
|
xfs_bmap_free_t free_list;
|
|
xfs_bmap_free_t free_list;
|
|
xfs_fsblock_t first_block;
|
|
xfs_fsblock_t first_block;
|
|
@@ -2120,8 +1962,10 @@ xfs_remove(
|
|
int committed;
|
|
int committed;
|
|
int link_zero;
|
|
int link_zero;
|
|
uint resblks;
|
|
uint resblks;
|
|
|
|
+ uint log_count;
|
|
|
|
|
|
xfs_itrace_entry(dp);
|
|
xfs_itrace_entry(dp);
|
|
|
|
+ xfs_itrace_entry(ip);
|
|
|
|
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
|
return XFS_ERROR(EIO);
|
|
return XFS_ERROR(EIO);
|
|
@@ -2134,19 +1978,23 @@ xfs_remove(
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
- xfs_itrace_entry(ip);
|
|
|
|
- xfs_itrace_ref(ip);
|
|
|
|
-
|
|
|
|
error = XFS_QM_DQATTACH(mp, dp, 0);
|
|
error = XFS_QM_DQATTACH(mp, dp, 0);
|
|
- if (!error)
|
|
|
|
- error = XFS_QM_DQATTACH(mp, ip, 0);
|
|
|
|
- if (error) {
|
|
|
|
- REMOVE_DEBUG_TRACE(__LINE__);
|
|
|
|
|
|
+ if (error)
|
|
|
|
+ goto std_return;
|
|
|
|
+
|
|
|
|
+ error = XFS_QM_DQATTACH(mp, ip, 0);
|
|
|
|
+ if (error)
|
|
goto std_return;
|
|
goto std_return;
|
|
- }
|
|
|
|
|
|
|
|
- tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
|
|
|
|
|
|
+ if (is_dir) {
|
|
|
|
+ tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
|
|
|
|
+ log_count = XFS_DEFAULT_LOG_COUNT;
|
|
|
|
+ } else {
|
|
|
|
+ tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
|
|
|
|
+ log_count = XFS_REMOVE_LOG_COUNT;
|
|
|
|
+ }
|
|
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
|
|
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* We try to get the real space reservation first,
|
|
* We try to get the real space reservation first,
|
|
* allowing for directory btree deletion(s) implying
|
|
* allowing for directory btree deletion(s) implying
|
|
@@ -2158,25 +2006,21 @@ xfs_remove(
|
|
*/
|
|
*/
|
|
resblks = XFS_REMOVE_SPACE_RES(mp);
|
|
resblks = XFS_REMOVE_SPACE_RES(mp);
|
|
error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
|
|
error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
|
|
- XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_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_REMOVE_LOG_RES(mp), 0,
|
|
error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
|
|
- XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
|
|
|
|
|
|
+ XFS_TRANS_PERM_LOG_RES, log_count);
|
|
}
|
|
}
|
|
if (error) {
|
|
if (error) {
|
|
ASSERT(error != ENOSPC);
|
|
ASSERT(error != ENOSPC);
|
|
- REMOVE_DEBUG_TRACE(__LINE__);
|
|
|
|
- xfs_trans_cancel(tp, 0);
|
|
|
|
- return error;
|
|
|
|
|
|
+ cancel_flags = 0;
|
|
|
|
+ goto out_trans_cancel;
|
|
}
|
|
}
|
|
|
|
|
|
error = xfs_lock_dir_and_entry(dp, ip);
|
|
error = xfs_lock_dir_and_entry(dp, ip);
|
|
- if (error) {
|
|
|
|
- REMOVE_DEBUG_TRACE(__LINE__);
|
|
|
|
- xfs_trans_cancel(tp, cancel_flags);
|
|
|
|
- goto std_return;
|
|
|
|
- }
|
|
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_trans_cancel;
|
|
|
|
|
|
/*
|
|
/*
|
|
* At this point, we've gotten both the directory and the entry
|
|
* At this point, we've gotten both the directory and the entry
|
|
@@ -2188,6 +2032,21 @@ xfs_remove(
|
|
IHOLD(dp);
|
|
IHOLD(dp);
|
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If we're removing a directory perform some additional validation.
|
|
|
|
+ */
|
|
|
|
+ if (is_dir) {
|
|
|
|
+ ASSERT(ip->i_d.di_nlink >= 2);
|
|
|
|
+ if (ip->i_d.di_nlink != 2) {
|
|
|
|
+ error = XFS_ERROR(ENOTEMPTY);
|
|
|
|
+ goto out_trans_cancel;
|
|
|
|
+ }
|
|
|
|
+ if (!xfs_dir_isempty(ip)) {
|
|
|
|
+ error = XFS_ERROR(ENOTEMPTY);
|
|
|
|
+ goto out_trans_cancel;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
|
|
* Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
|
|
*/
|
|
*/
|
|
@@ -2196,39 +2055,64 @@ xfs_remove(
|
|
&first_block, &free_list, resblks);
|
|
&first_block, &free_list, resblks);
|
|
if (error) {
|
|
if (error) {
|
|
ASSERT(error != ENOENT);
|
|
ASSERT(error != ENOENT);
|
|
- REMOVE_DEBUG_TRACE(__LINE__);
|
|
|
|
- goto error1;
|
|
|
|
|
|
+ goto out_bmap_cancel;
|
|
}
|
|
}
|
|
xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
|
xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Bump the in memory generation count on the parent
|
|
|
|
+ * directory so that other can know that it has changed.
|
|
|
|
+ */
|
|
dp->i_gen++;
|
|
dp->i_gen++;
|
|
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
|
|
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
|
|
|
|
|
|
- error = xfs_droplink(tp, ip);
|
|
|
|
- if (error) {
|
|
|
|
- REMOVE_DEBUG_TRACE(__LINE__);
|
|
|
|
- goto error1;
|
|
|
|
|
|
+ if (is_dir) {
|
|
|
|
+ /*
|
|
|
|
+ * Drop the link from ip's "..".
|
|
|
|
+ */
|
|
|
|
+ error = xfs_droplink(tp, dp);
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_bmap_cancel;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Drop the link from dp to ip.
|
|
|
|
+ */
|
|
|
|
+ error = xfs_droplink(tp, ip);
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_bmap_cancel;
|
|
|
|
+ } else {
|
|
|
|
+ /*
|
|
|
|
+ * When removing a non-directory we need to log the parent
|
|
|
|
+ * inode here for the i_gen update. For a directory this is
|
|
|
|
+ * done implicitly by the xfs_droplink call for the ".." entry.
|
|
|
|
+ */
|
|
|
|
+ xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
|
|
}
|
|
}
|
|
|
|
|
|
- /* Determine if this is the last link while
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Drop the "." link from ip to self.
|
|
|
|
+ */
|
|
|
|
+ error = xfs_droplink(tp, ip);
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_bmap_cancel;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Determine if this is the last link while
|
|
* we are in the transaction.
|
|
* we are in the transaction.
|
|
*/
|
|
*/
|
|
- link_zero = (ip)->i_d.di_nlink==0;
|
|
|
|
|
|
+ link_zero = (ip->i_d.di_nlink == 0);
|
|
|
|
|
|
/*
|
|
/*
|
|
* If this is a synchronous mount, make sure that the
|
|
* If this is a synchronous mount, make sure that the
|
|
* remove transaction goes to disk before returning to
|
|
* remove 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);
|
|
- }
|
|
|
|
|
|
|
|
error = xfs_bmap_finish(&tp, &free_list, &committed);
|
|
error = xfs_bmap_finish(&tp, &free_list, &committed);
|
|
- if (error) {
|
|
|
|
- REMOVE_DEBUG_TRACE(__LINE__);
|
|
|
|
- goto error_rele;
|
|
|
|
- }
|
|
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_bmap_cancel;
|
|
|
|
|
|
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
|
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
|
if (error)
|
|
if (error)
|
|
@@ -2240,38 +2124,26 @@ xfs_remove(
|
|
* will get killed on last close in xfs_close() so we don't
|
|
* will get killed on last close in xfs_close() so we don't
|
|
* have to worry about that.
|
|
* have to worry about that.
|
|
*/
|
|
*/
|
|
- if (link_zero && xfs_inode_is_filestream(ip))
|
|
|
|
|
|
+ if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
|
|
xfs_filestream_deassociate(ip);
|
|
xfs_filestream_deassociate(ip);
|
|
|
|
|
|
xfs_itrace_exit(ip);
|
|
xfs_itrace_exit(ip);
|
|
|
|
+ xfs_itrace_exit(dp);
|
|
|
|
|
|
-/* Fall through to std_return with error = 0 */
|
|
|
|
std_return:
|
|
std_return:
|
|
if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
|
|
if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
|
|
- (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
|
|
|
|
- dp, DM_RIGHT_NULL,
|
|
|
|
- NULL, DM_RIGHT_NULL,
|
|
|
|
- name->name, NULL, ip->i_d.di_mode, error, 0);
|
|
|
|
|
|
+ XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
|
|
|
|
+ NULL, DM_RIGHT_NULL, name->name, NULL,
|
|
|
|
+ ip->i_d.di_mode, error, 0);
|
|
}
|
|
}
|
|
- return error;
|
|
|
|
|
|
|
|
- error1:
|
|
|
|
- xfs_bmap_cancel(&free_list);
|
|
|
|
- cancel_flags |= XFS_TRANS_ABORT;
|
|
|
|
- xfs_trans_cancel(tp, cancel_flags);
|
|
|
|
- goto std_return;
|
|
|
|
|
|
+ return error;
|
|
|
|
|
|
- error_rele:
|
|
|
|
- /*
|
|
|
|
- * In this case make sure to not release the inode until after
|
|
|
|
- * the current transaction is aborted. Releasing it beforehand
|
|
|
|
- * can cause us to go to xfs_inactive and start a recursive
|
|
|
|
- * transaction which can easily deadlock with the current one.
|
|
|
|
- */
|
|
|
|
|
|
+ out_bmap_cancel:
|
|
xfs_bmap_cancel(&free_list);
|
|
xfs_bmap_cancel(&free_list);
|
|
cancel_flags |= XFS_TRANS_ABORT;
|
|
cancel_flags |= XFS_TRANS_ABORT;
|
|
|
|
+ out_trans_cancel:
|
|
xfs_trans_cancel(tp, cancel_flags);
|
|
xfs_trans_cancel(tp, cancel_flags);
|
|
-
|
|
|
|
goto std_return;
|
|
goto std_return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2637,186 +2509,6 @@ std_return:
|
|
goto std_return;
|
|
goto std_return;
|
|
}
|
|
}
|
|
|
|
|
|
-int
|
|
|
|
-xfs_rmdir(
|
|
|
|
- xfs_inode_t *dp,
|
|
|
|
- struct xfs_name *name,
|
|
|
|
- xfs_inode_t *cdp)
|
|
|
|
-{
|
|
|
|
- xfs_mount_t *mp = dp->i_mount;
|
|
|
|
- xfs_trans_t *tp;
|
|
|
|
- int error;
|
|
|
|
- xfs_bmap_free_t free_list;
|
|
|
|
- xfs_fsblock_t first_block;
|
|
|
|
- int cancel_flags;
|
|
|
|
- int committed;
|
|
|
|
- int last_cdp_link;
|
|
|
|
- uint resblks;
|
|
|
|
-
|
|
|
|
- xfs_itrace_entry(dp);
|
|
|
|
-
|
|
|
|
- if (XFS_FORCED_SHUTDOWN(mp))
|
|
|
|
- return XFS_ERROR(EIO);
|
|
|
|
-
|
|
|
|
- if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
|
|
|
|
- error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
|
|
|
|
- dp, DM_RIGHT_NULL,
|
|
|
|
- NULL, DM_RIGHT_NULL, name->name,
|
|
|
|
- NULL, cdp->i_d.di_mode, 0, 0);
|
|
|
|
- if (error)
|
|
|
|
- return XFS_ERROR(error);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Get the dquots for the inodes.
|
|
|
|
- */
|
|
|
|
- error = XFS_QM_DQATTACH(mp, dp, 0);
|
|
|
|
- if (!error)
|
|
|
|
- error = XFS_QM_DQATTACH(mp, cdp, 0);
|
|
|
|
- if (error) {
|
|
|
|
- REMOVE_DEBUG_TRACE(__LINE__);
|
|
|
|
- goto std_return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
|
|
|
|
- cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
|
|
|
|
- /*
|
|
|
|
- * We try to get the real space reservation first,
|
|
|
|
- * allowing for directory btree deletion(s) implying
|
|
|
|
- * possible bmap insert(s). If we can't get the space
|
|
|
|
- * reservation then we use 0 instead, and avoid the bmap
|
|
|
|
- * btree insert(s) in the directory code by, if the bmap
|
|
|
|
- * insert tries to happen, instead trimming the LAST
|
|
|
|
- * block from the directory.
|
|
|
|
- */
|
|
|
|
- resblks = XFS_REMOVE_SPACE_RES(mp);
|
|
|
|
- error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
|
|
|
|
- XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
|
|
|
|
- if (error == ENOSPC) {
|
|
|
|
- resblks = 0;
|
|
|
|
- error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
|
|
|
|
- XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
|
|
|
|
- }
|
|
|
|
- if (error) {
|
|
|
|
- ASSERT(error != ENOSPC);
|
|
|
|
- cancel_flags = 0;
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
- XFS_BMAP_INIT(&free_list, &first_block);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Now lock the child directory inode and the parent directory
|
|
|
|
- * inode in the proper order. This will take care of validating
|
|
|
|
- * that the directory entry for the child directory inode has
|
|
|
|
- * not changed while we were obtaining a log reservation.
|
|
|
|
- */
|
|
|
|
- error = xfs_lock_dir_and_entry(dp, cdp);
|
|
|
|
- if (error) {
|
|
|
|
- xfs_trans_cancel(tp, cancel_flags);
|
|
|
|
- goto std_return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- IHOLD(dp);
|
|
|
|
- xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
|
|
|
|
-
|
|
|
|
- IHOLD(cdp);
|
|
|
|
- xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
|
|
|
|
-
|
|
|
|
- ASSERT(cdp->i_d.di_nlink >= 2);
|
|
|
|
- if (cdp->i_d.di_nlink != 2) {
|
|
|
|
- error = XFS_ERROR(ENOTEMPTY);
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
- if (!xfs_dir_isempty(cdp)) {
|
|
|
|
- error = XFS_ERROR(ENOTEMPTY);
|
|
|
|
- goto error_return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
|
|
|
|
- &first_block, &free_list, resblks);
|
|
|
|
- if (error)
|
|
|
|
- goto error1;
|
|
|
|
-
|
|
|
|
- xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Bump the in memory generation count on the parent
|
|
|
|
- * directory so that other can know that it has changed.
|
|
|
|
- */
|
|
|
|
- dp->i_gen++;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Drop the link from cdp's "..".
|
|
|
|
- */
|
|
|
|
- error = xfs_droplink(tp, dp);
|
|
|
|
- if (error) {
|
|
|
|
- goto error1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Drop the link from dp to cdp.
|
|
|
|
- */
|
|
|
|
- error = xfs_droplink(tp, cdp);
|
|
|
|
- if (error) {
|
|
|
|
- goto error1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Drop the "." link from cdp to self.
|
|
|
|
- */
|
|
|
|
- error = xfs_droplink(tp, cdp);
|
|
|
|
- if (error) {
|
|
|
|
- goto error1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Determine these before committing transaction */
|
|
|
|
- last_cdp_link = (cdp)->i_d.di_nlink==0;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * If this is a synchronous mount, make sure that the
|
|
|
|
- * rmdir 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) {
|
|
|
|
- xfs_bmap_cancel(&free_list);
|
|
|
|
- xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
|
|
|
|
- XFS_TRANS_ABORT));
|
|
|
|
- goto std_return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
|
|
|
- if (error) {
|
|
|
|
- goto std_return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /* Fall through to std_return with error = 0 or the errno
|
|
|
|
- * from xfs_trans_commit. */
|
|
|
|
- std_return:
|
|
|
|
- if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
|
|
|
|
- (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
|
|
|
|
- dp, DM_RIGHT_NULL,
|
|
|
|
- NULL, DM_RIGHT_NULL,
|
|
|
|
- name->name, NULL, cdp->i_d.di_mode,
|
|
|
|
- error, 0);
|
|
|
|
- }
|
|
|
|
- return error;
|
|
|
|
-
|
|
|
|
- error1:
|
|
|
|
- xfs_bmap_cancel(&free_list);
|
|
|
|
- cancel_flags |= XFS_TRANS_ABORT;
|
|
|
|
- /* FALLTHROUGH */
|
|
|
|
-
|
|
|
|
- error_return:
|
|
|
|
- xfs_trans_cancel(tp, cancel_flags);
|
|
|
|
- goto std_return;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
int
|
|
int
|
|
xfs_symlink(
|
|
xfs_symlink(
|
|
xfs_inode_t *dp,
|
|
xfs_inode_t *dp,
|
|
@@ -3242,7 +2934,6 @@ xfs_finish_reclaim(
|
|
{
|
|
{
|
|
xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
|
|
xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
|
|
bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
|
|
bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
|
|
- int error;
|
|
|
|
|
|
|
|
if (vp && VN_BAD(vp))
|
|
if (vp && VN_BAD(vp))
|
|
goto reclaim;
|
|
goto reclaim;
|
|
@@ -3285,29 +2976,16 @@ xfs_finish_reclaim(
|
|
xfs_iflock(ip);
|
|
xfs_iflock(ip);
|
|
}
|
|
}
|
|
|
|
|
|
- if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
|
|
|
|
- if (ip->i_update_core ||
|
|
|
|
- ((ip->i_itemp != NULL) &&
|
|
|
|
- (ip->i_itemp->ili_format.ilf_fields != 0))) {
|
|
|
|
- error = xfs_iflush(ip, sync_mode);
|
|
|
|
- /*
|
|
|
|
- * If we hit an error, typically because of filesystem
|
|
|
|
- * shutdown, we don't need to let vn_reclaim to know
|
|
|
|
- * because we're gonna reclaim the inode anyway.
|
|
|
|
- */
|
|
|
|
- if (error) {
|
|
|
|
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
|
|
- goto reclaim;
|
|
|
|
- }
|
|
|
|
- xfs_iflock(ip); /* synchronize with xfs_iflush_done */
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ASSERT(ip->i_update_core == 0);
|
|
|
|
- ASSERT(ip->i_itemp == NULL ||
|
|
|
|
- ip->i_itemp->ili_format.ilf_fields == 0);
|
|
|
|
|
|
+ /*
|
|
|
|
+ * In the case of a forced shutdown we rely on xfs_iflush() to
|
|
|
|
+ * wait for the inode to be unpinned before returning an error.
|
|
|
|
+ */
|
|
|
|
+ if (xfs_iflush(ip, sync_mode) == 0) {
|
|
|
|
+ /* synchronize with xfs_iflush_done */
|
|
|
|
+ xfs_iflock(ip);
|
|
|
|
+ xfs_ifunlock(ip);
|
|
}
|
|
}
|
|
|
|
|
|
- xfs_ifunlock(ip);
|
|
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
|
|
|
|
reclaim:
|
|
reclaim:
|
|
@@ -3418,7 +3096,7 @@ xfs_alloc_file_space(
|
|
|
|
|
|
/* Generate a DMAPI event if needed. */
|
|
/* Generate a DMAPI event if needed. */
|
|
if (alloc_type != 0 && offset < ip->i_size &&
|
|
if (alloc_type != 0 && offset < ip->i_size &&
|
|
- (attr_flags&ATTR_DMI) == 0 &&
|
|
|
|
|
|
+ (attr_flags & XFS_ATTR_DMI) == 0 &&
|
|
DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
|
|
DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
|
|
xfs_off_t end_dmi_offset;
|
|
xfs_off_t end_dmi_offset;
|
|
|
|
|
|
@@ -3532,7 +3210,7 @@ retry:
|
|
allocatesize_fsb -= allocated_fsb;
|
|
allocatesize_fsb -= allocated_fsb;
|
|
}
|
|
}
|
|
dmapi_enospc_check:
|
|
dmapi_enospc_check:
|
|
- if (error == ENOSPC && (attr_flags & ATTR_DMI) == 0 &&
|
|
|
|
|
|
+ if (error == ENOSPC && (attr_flags & XFS_ATTR_DMI) == 0 &&
|
|
DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) {
|
|
DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) {
|
|
error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE,
|
|
error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE,
|
|
ip, DM_RIGHT_NULL,
|
|
ip, DM_RIGHT_NULL,
|
|
@@ -3679,7 +3357,7 @@ xfs_free_file_space(
|
|
end_dmi_offset = offset + len;
|
|
end_dmi_offset = offset + len;
|
|
endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
|
|
endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
|
|
|
|
|
|
- if (offset < ip->i_size && (attr_flags & ATTR_DMI) == 0 &&
|
|
|
|
|
|
+ if (offset < ip->i_size && (attr_flags & XFS_ATTR_DMI) == 0 &&
|
|
DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
|
|
DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
|
|
if (end_dmi_offset > ip->i_size)
|
|
if (end_dmi_offset > ip->i_size)
|
|
end_dmi_offset = ip->i_size;
|
|
end_dmi_offset = ip->i_size;
|
|
@@ -3690,7 +3368,7 @@ xfs_free_file_space(
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
- if (attr_flags & ATTR_NOLOCK)
|
|
|
|
|
|
+ if (attr_flags & XFS_ATTR_NOLOCK)
|
|
need_iolock = 0;
|
|
need_iolock = 0;
|
|
if (need_iolock) {
|
|
if (need_iolock) {
|
|
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
|
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
|
@@ -3867,7 +3545,7 @@ xfs_change_file_space(
|
|
xfs_off_t startoffset;
|
|
xfs_off_t startoffset;
|
|
xfs_off_t llen;
|
|
xfs_off_t llen;
|
|
xfs_trans_t *tp;
|
|
xfs_trans_t *tp;
|
|
- bhv_vattr_t va;
|
|
|
|
|
|
+ struct iattr iattr;
|
|
|
|
|
|
xfs_itrace_entry(ip);
|
|
xfs_itrace_entry(ip);
|
|
|
|
|
|
@@ -3941,10 +3619,10 @@ xfs_change_file_space(
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- va.va_mask = XFS_AT_SIZE;
|
|
|
|
- va.va_size = startoffset;
|
|
|
|
|
|
+ iattr.ia_valid = ATTR_SIZE;
|
|
|
|
+ iattr.ia_size = startoffset;
|
|
|
|
|
|
- error = xfs_setattr(ip, &va, attr_flags, credp);
|
|
|
|
|
|
+ error = xfs_setattr(ip, &iattr, attr_flags, credp);
|
|
|
|
|
|
if (error)
|
|
if (error)
|
|
return error;
|
|
return error;
|
|
@@ -3974,7 +3652,7 @@ xfs_change_file_space(
|
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
|
xfs_trans_ihold(tp, ip);
|
|
xfs_trans_ihold(tp, ip);
|
|
|
|
|
|
- if ((attr_flags & ATTR_DMI) == 0) {
|
|
|
|
|
|
+ if ((attr_flags & XFS_ATTR_DMI) == 0) {
|
|
ip->i_d.di_mode &= ~S_ISUID;
|
|
ip->i_d.di_mode &= ~S_ISUID;
|
|
|
|
|
|
/*
|
|
/*
|