/*
* xfs_setattr
*/
-STATIC int
+int
xfs_setattr(
bhv_desc_t *bdp,
vattr_t *vap,
int mandlock_before, mandlock_after;
struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
int file_owner;
+ int need_iolock = (flags & ATTR_DMI) == 0;
vp = BHV_TO_VNODE(bdp);
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
goto error_return;
}
}
- lock_flags |= XFS_IOLOCK_EXCL;
+ if (need_iolock)
+ lock_flags |= XFS_IOLOCK_EXCL;
}
xfs_ilock(ip, lock_flags);
XFS_TRANS_PERM_LOG_RES,
XFS_ITRUNCATE_LOG_COUNT))) {
xfs_trans_cancel(tp, 0);
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ if (need_iolock)
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return code;
}
commit_flags = XFS_TRANS_RELEASE_LOG_RES;
mp->m_sb.sb_blocklog;
}
if (mask & XFS_AT_XFLAGS) {
- ip->i_d.di_flags = 0;
- if (vap->va_xflags & XFS_XFLAG_REALTIME) {
- ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
- ip->i_iocore.io_flags |= XFS_IOCORE_RT;
- }
+ 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)
- ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE;
+ di_flags |= XFS_DIFLAG_IMMUTABLE;
if (vap->va_xflags & XFS_XFLAG_IUNLINK)
- ip->i_d.di_flags |= XFS_DIFLAG_IUNLINK;
+ di_flags |= XFS_DIFLAG_IUNLINK;
if (vap->va_xflags & XFS_XFLAG_BARRIER)
- ip->i_d.di_flags |= XFS_DIFLAG_BARRIER;
+ di_flags |= XFS_DIFLAG_BARRIER;
if (vap->va_xflags & XFS_XFLAG_APPEND)
- ip->i_d.di_flags |= XFS_DIFLAG_APPEND;
+ di_flags |= XFS_DIFLAG_APPEND;
if (vap->va_xflags & XFS_XFLAG_SYNC)
- ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+ di_flags |= XFS_DIFLAG_SYNC;
if (vap->va_xflags & XFS_XFLAG_NOATIME)
- ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
+ di_flags |= XFS_DIFLAG_NOATIME;
if (vap->va_xflags & XFS_XFLAG_NODUMP)
- ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
- /* can't set PREALLOC this way, just ignore it */
+ di_flags |= XFS_DIFLAG_NODUMP;
+ 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;
+ } else {
+ if (vap->va_xflags & XFS_XFLAG_REALTIME) {
+ di_flags |= XFS_DIFLAG_REALTIME;
+ ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+ } else {
+ ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
+ }
+ }
+ ip->i_d.di_flags = di_flags;
}
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
timeflags |= XFS_ICHGTIME_CHG;
* If the inode is already free, then there can be nothing
* to clean up here.
*/
- if (ip->i_d.di_mode == 0) {
+ if (ip->i_d.di_mode == 0 || VN_BAD(vp)) {
ASSERT(ip->i_df.if_real_bytes == 0);
ASSERT(ip->i_df.if_broot_bytes == 0);
return VN_INACTIVE_CACHE;
}
-#define XFS_CREATE_NEW_MAXTRIES 10000
-
/*
* xfs_create (create a new file).
*/
xfs_ilock(dp, XFS_ILOCK_EXCL);
+ /*
+ * Check whether the directory allows new symlinks or not.
+ */
+ if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
+ error = XFS_ERROR(EPERM);
+ goto error_return;
+ }
+
/*
* Reserve disk quota : blocks and inode.
*/
vnode_t *vp;
vp = BHV_TO_VNODE(bdp);
+ ip = XFS_BHVTOI(bdp);
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
ASSERT(!VN_MAPPED(vp));
- ip = XFS_BHVTOI(bdp);
+
+ /* bad inode, get out here ASAP */
+ if (VN_BAD(vp)) {
+ xfs_ireclaim(ip);
+ return 0;
+ }
if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
if (ip->i_d.di_size > 0) {
int sync_mode)
{
xfs_ihash_t *ih = ip->i_hash;
+ vnode_t *vp = XFS_ITOV_NULL(ip);
int error;
+ if (vp && VN_BAD(vp))
+ return 0;
+
/* The hash lock here protects a thread in xfs_iget_core from
* racing with us on linking the inode back with a vnode.
* Once we have the XFS_IRECLAIM flag set it will not touch
*/
write_lock(&ih->ih_lock);
if ((ip->i_flags & XFS_IRECLAIM) ||
- (!(ip->i_flags & XFS_IRECLAIMABLE) &&
- (XFS_ITOV_NULL(ip) == NULL))) {
+ (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
write_unlock(&ih->ih_lock);
if (locked) {
xfs_ifunlock(ip);
xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
{
int purged;
- struct list_head *curr, *next;
- xfs_inode_t *ip;
+ xfs_inode_t *ip, *n;
int done = 0;
while (!done) {
purged = 0;
XFS_MOUNT_ILOCK(mp);
- list_for_each_safe(curr, next, &mp->m_del_inodes) {
- ip = list_entry(curr, xfs_inode_t, i_reclaim);
+ list_for_each_entry_safe(ip, n, &mp->m_del_inodes, i_reclaim) {
if (noblock) {
if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0)
continue;
int rt;
xfs_fileoff_t startoffset_fsb;
xfs_trans_t *tp;
+ int need_iolock = (attr_flags & ATTR_DMI) == 0;
vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
mp = ip->i_mount;
return(error);
}
- xfs_ilock(ip, XFS_IOLOCK_EXCL);
+ if (need_iolock)
+ xfs_ilock(ip, XFS_IOLOCK_EXCL);
rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
(__uint8_t)NBPP);
ilen = len + (offset & (rounding - 1));
error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0,
&imap, &nimap, NULL);
if (error)
- return error;
+ goto out_unlock_iolock;
ASSERT(nimap == 0 || nimap == 1);
if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
xfs_daddr_t block;
error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0,
&imap, &nimap, NULL);
if (error)
- return error;
+ goto out_unlock_iolock;
ASSERT(nimap == 0 || nimap == 1);
if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
}
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ out_unlock_iolock:
+ if (need_iolock)
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return error;
error0:
xfs_bmap_cancel(&free_list);
error1:
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
- xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+ xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) :
+ XFS_ILOCK_EXCL);
return error;
}
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
xfs_trans_ihold(tp, ip);
- ip->i_d.di_mode &= ~S_ISUID;
-
- /*
- * Note that we don't have to worry about mandatory
- * file locking being disabled here because we only
- * clear the S_ISGID bit if the Group execute bit is
- * on, but if it was on then mandatory locking wouldn't
- * have been enabled.
- */
- if (ip->i_d.di_mode & S_IXGRP)
- ip->i_d.di_mode &= ~S_ISGID;
+ if ((attr_flags & ATTR_DMI) == 0) {
+ ip->i_d.di_mode &= ~S_ISUID;
- xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+ /*
+ * Note that we don't have to worry about mandatory
+ * file locking being disabled here because we only
+ * clear the S_ISGID bit if the Group execute bit is
+ * on, but if it was on then mandatory locking wouldn't
+ * have been enabled.
+ */
+ if (ip->i_d.di_mode & S_IXGRP)
+ ip->i_d.di_mode &= ~S_ISGID;
+ xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+ }
if (setprealloc)
ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
else if (clrprealloc)