.error_level = { 0, 3, 11 },
.sync_interval = { HZ, 30*HZ, 60*HZ },
.stats_clear = { 0, 0, 1 },
+ .inherit_sync = { 0, 1, 1 },
+ .inherit_nodump = { 0, 1, 1 },
};
/*
#include <linux/namei.h>
#include <linux/pagemap.h>
+/*
+ * ioctl commands that are used by Linux filesystems
+ */
+#define XFS_IOC_GETXFLAGS _IOR('f', 1, long)
+#define XFS_IOC_SETXFLAGS _IOW('f', 2, long)
+#define XFS_IOC_GETVERSION _IOR('v', 1, long)
+
/*
* xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
if (permflag & O_TRUNC)
permflag |= 2;
+ if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
+ (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
+ iput(inode);
+ return -XFS_ERROR(EPERM);
+ }
+
+ if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
+ iput(inode);
+ return -XFS_ERROR(EACCES);
+ }
+
/* Can't write directories. */
if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
iput(inode);
if (error)
return -error;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+ VN_RELE(vp);
+ return -XFS_ERROR(EPERM);
+ }
+
if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
VN_RELE(vp);
return -XFS_ERROR(EFAULT);
NULL, ops[i].am_error);
break;
case ATTR_OP_SET:
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+ ops[i].am_error = EPERM;
+ break;
+ }
VOP_ATTR_SET(vp,ops[i].am_attrname, ops[i].am_attrvalue,
ops[i].am_length, ops[i].am_flags,
NULL, ops[i].am_error);
break;
case ATTR_OP_REMOVE:
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+ ops[i].am_error = EPERM;
+ break;
+ }
VOP_ATTR_REMOVE(vp, ops[i].am_attrname, ops[i].am_flags,
NULL, ops[i].am_error);
break;
STATIC int
xfs_ioc_xattr(
vnode_t *vp,
+ xfs_inode_t *ip,
struct file *filp,
unsigned int cmd,
unsigned long arg);
case XFS_IOC_FSGEOMETRY:
return xfs_ioc_fsgeometry(mp, arg);
+ case XFS_IOC_GETVERSION:
+ case XFS_IOC_GETXFLAGS:
+ case XFS_IOC_SETXFLAGS:
case XFS_IOC_FSGETXATTR:
case XFS_IOC_FSSETXATTR:
case XFS_IOC_FSGETXATTRA:
- return xfs_ioc_xattr(vp, filp, cmd, arg);
+ return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
case XFS_IOC_FSSETDM: {
struct fsdmidata dmi;
int attr_flags = 0;
int error;
+ if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+ return -XFS_ERROR(EPERM);
+
if (filp->f_flags & O_RDONLY)
return -XFS_ERROR(EBADF);
return 0;
}
+/*
+ * Linux extended inode flags interface.
+ */
+#define LINUX_XFLAG_SYNC 0x00000008 /* Synchronous updates */
+#define LINUX_XFLAG_IMMUTABLE 0x00000010 /* Immutable file */
+#define LINUX_XFLAG_APPEND 0x00000020 /* writes to file may only append */
+#define LINUX_XFLAG_NODUMP 0x00000040 /* do not dump file */
+#define LINUX_XFLAG_NOATIME 0x00000080 /* do not update atime */
+
+STATIC unsigned int
+xfs_merge_ioc_xflags(
+ unsigned int flags,
+ unsigned int start)
+{
+ unsigned int xflags = start;
+
+ if (flags & LINUX_XFLAG_IMMUTABLE)
+ xflags |= XFS_XFLAG_IMMUTABLE;
+ else
+ xflags &= ~XFS_XFLAG_IMMUTABLE;
+ if (flags & LINUX_XFLAG_APPEND)
+ xflags |= XFS_XFLAG_APPEND;
+ else
+ xflags &= ~XFS_XFLAG_APPEND;
+ if (flags & LINUX_XFLAG_SYNC)
+ xflags |= XFS_XFLAG_SYNC;
+ else
+ xflags &= ~XFS_XFLAG_SYNC;
+ if (flags & LINUX_XFLAG_NOATIME)
+ xflags |= XFS_XFLAG_NOATIME;
+ else
+ xflags &= ~XFS_XFLAG_NOATIME;
+ if (flags & LINUX_XFLAG_NODUMP)
+ xflags |= XFS_XFLAG_NODUMP;
+ else
+ xflags &= ~XFS_XFLAG_NODUMP;
+
+ return xflags;
+}
+
STATIC int
xfs_ioc_xattr(
vnode_t *vp,
+ xfs_inode_t *ip,
struct file *filp,
unsigned int cmd,
unsigned long arg)
struct fsxattr fa;
vattr_t va;
int error;
+ int attr_flags;
+ unsigned int flags;
switch (cmd) {
case XFS_IOC_FSGETXATTR: {
}
case XFS_IOC_FSSETXATTR: {
- int attr_flags = 0;
-
if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa)))
return -XFS_ERROR(EFAULT);
+ attr_flags = 0;
+ if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+ attr_flags |= ATTR_NONBLOCK;
+
va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;
va.va_xflags = fa.fsx_xflags;
va.va_extsize = fa.fsx_extsize;
- if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
- attr_flags |= ATTR_NONBLOCK;
-
VOP_SETATTR(vp, &va, attr_flags, NULL, error);
+ if (!error)
+ vn_revalidate(vp); /* update Linux inode flags */
return -error;
}
case XFS_IOC_FSGETXATTRA: {
-
va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;
VOP_GETATTR(vp, &va, 0, NULL, error);
if (error)
return 0;
}
+ case XFS_IOC_GETXFLAGS: {
+ flags = 0;
+ if (ip->i_d.di_flags & XFS_XFLAG_IMMUTABLE)
+ flags |= LINUX_XFLAG_IMMUTABLE;
+ if (ip->i_d.di_flags & XFS_XFLAG_APPEND)
+ flags |= LINUX_XFLAG_APPEND;
+ if (ip->i_d.di_flags & XFS_XFLAG_SYNC)
+ flags |= LINUX_XFLAG_SYNC;
+ if (ip->i_d.di_flags & XFS_XFLAG_NOATIME)
+ flags |= LINUX_XFLAG_NOATIME;
+ if (ip->i_d.di_flags & XFS_XFLAG_NODUMP)
+ flags |= LINUX_XFLAG_NODUMP;
+ if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+ return -XFS_ERROR(EFAULT);
+ return 0;
+ }
+
+ case XFS_IOC_SETXFLAGS: {
+ if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags)))
+ return -XFS_ERROR(EFAULT);
+
+ if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
+ LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
+ LINUX_XFLAG_SYNC))
+ return -XFS_ERROR(EOPNOTSUPP);
+
+ attr_flags = 0;
+ if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+ attr_flags |= ATTR_NONBLOCK;
+
+ va.va_mask = XFS_AT_XFLAGS;
+ va.va_xflags = xfs_merge_ioc_xflags(flags, ip->i_d.di_flags);
+
+ VOP_SETATTR(vp, &va, attr_flags, NULL, error);
+ if (!error)
+ vn_revalidate(vp); /* update Linux inode flags */
+ return -error;
+ }
+
+ case XFS_IOC_GETVERSION: {
+ flags = LINVFS_GET_IP(vp)->i_generation;
+ if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+ return -XFS_ERROR(EFAULT);
+ return 0;
+ }
+
default:
return -ENOTTY;
-
}
}
return error;
}
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return -EPERM;
+
/* Convert Linux syscall to XFS internal ATTR flags */
if (flags & XATTR_CREATE)
xflags |= ATTR_CREATE;
return error;
}
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return -EPERM;
+
if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
xfs_namespaces[ROOT_NAMES].namelen) == 0) {
if (!capable(CAP_SYS_ADMIN))
#define xfs_error_level xfs_params.error_level.val
#define xfs_syncd_interval xfs_params.sync_interval.val
#define xfs_stats_clear xfs_params.stats_clear.val
+#define xfs_inherit_sync xfs_params.inherit_sync.val
+#define xfs_inherit_nodump xfs_params.inherit_nodump.val
#define NBPP PAGE_SIZE
#define DPPSHFT (PAGE_SHIFT - 9)
inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
-
+ if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE)
+ inode->i_flags |= S_IMMUTABLE;
+ else
+ inode->i_flags &= ~S_IMMUTABLE;
+ if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
+ inode->i_flags |= S_APPEND;
+ else
+ inode->i_flags &= ~S_APPEND;
+ if (ip->i_d.di_flags & XFS_DIFLAG_SYNC)
+ inode->i_flags |= S_SYNC;
+ else
+ inode->i_flags &= ~S_SYNC;
+ if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME)
+ inode->i_flags |= S_NOATIME;
+ else
+ inode->i_flags &= ~S_NOATIME;
vp->v_flag &= ~VMODIFIED;
}
&sysctl_intvec, NULL,
&xfs_params.sync_interval.min, &xfs_params.sync_interval.max},
+ {XFS_INHERIT_SYNC, "inherit_sync", &xfs_params.inherit_sync.val,
+ sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
+ &sysctl_intvec, NULL,
+ &xfs_params.inherit_sync.min, &xfs_params.inherit_sync.max},
+
+ {XFS_INHERIT_NODUMP, "inherit_nodump", &xfs_params.inherit_nodump.val,
+ sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
+ &sysctl_intvec, NULL,
+ &xfs_params.inherit_nodump.min, &xfs_params.inherit_nodump.max},
+
/* please keep this the last entry */
#ifdef CONFIG_PROC_FS
{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
xfs_sysctl_val_t error_level; /* Degree of reporting for problems */
xfs_sysctl_val_t sync_interval; /* time between sync calls */
xfs_sysctl_val_t stats_clear; /* Reset all XFS statistics to zero. */
+ xfs_sysctl_val_t inherit_sync; /* Inherit the "sync" inode flag. */
+ xfs_sysctl_val_t inherit_nodump;/* Inherit the "nodump" inode flag. */
} xfs_param_t;
/*
*/
enum {
- XFS_RESTRICT_CHOWN = 1,
- XFS_SGID_INHERIT = 2,
- XFS_SYMLINK_MODE = 3,
- XFS_PANIC_MASK = 4,
- XFS_ERRLEVEL = 5,
- XFS_SYNC_INTERVAL = 6,
- XFS_STATS_CLEAR = 7,
+ XFS_RESTRICT_CHOWN = 3,
+ XFS_SGID_INHERIT = 4,
+ XFS_SYMLINK_MODE = 5,
+ XFS_PANIC_MASK = 6,
+ XFS_ERRLEVEL = 7,
+ XFS_SYNC_INTERVAL = 8,
+ XFS_STATS_CLEAR = 12,
+ XFS_INHERIT_SYNC = 13,
+ XFS_INHERIT_NODUMP = 14,
};
extern xfs_param_t xfs_params;
inode->i_ctime = va.va_ctime;
inode->i_atime = va.va_atime;
i_size_write(inode, va.va_size);
+ if (va.va_xflags & XFS_XFLAG_IMMUTABLE)
+ inode->i_flags |= S_IMMUTABLE;
+ else
+ inode->i_flags &= ~S_IMMUTABLE;
+ if (va.va_xflags & XFS_XFLAG_APPEND)
+ inode->i_flags |= S_APPEND;
+ else
+ inode->i_flags &= ~S_APPEND;
+ if (va.va_xflags & XFS_XFLAG_SYNC)
+ inode->i_flags |= S_SYNC;
+ else
+ inode->i_flags &= ~S_SYNC;
+ if (va.va_xflags & XFS_XFLAG_NOATIME)
+ inode->i_flags |= S_NOATIME;
+ else
+ inode->i_flags &= ~S_NOATIME;
VUNMODIFY(vp);
}
return -error;
vattr_t va;
int error;
+ if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+ return EPERM;
if (kind == _ACL_TYPE_DEFAULT && vp->v_type != VDIR)
return ENOTDIR;
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
return EROFS;
+ if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+ return EPERM;
if ((error = _MAC_VACCESS(vp, NULL, VWRITE)))
return error;
va.va_mask = XFS_AT_UID;
* There should be a one-to-one correspondence between these flags and the
* XFS_XFLAG_s.
*/
-#define XFS_DIFLAG_REALTIME_BIT 0 /* file's blocks come from rt area */
-#define XFS_DIFLAG_PREALLOC_BIT 1 /* file space has been preallocated */
-#define XFS_DIFLAG_NEWRTBM_BIT 2 /* for rtbitmap inode, new format */
-#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT)
-#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT)
-#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT)
-#define XFS_DIFLAG_ALL \
- (XFS_DIFLAG_REALTIME|XFS_DIFLAG_PREALLOC|XFS_DIFLAG_NEWRTBM)
+#define XFS_DIFLAG_REALTIME_BIT 0 /* file's blocks come from rt area */
+#define XFS_DIFLAG_PREALLOC_BIT 1 /* file space has been preallocated */
+#define XFS_DIFLAG_NEWRTBM_BIT 2 /* for rtbitmap inode, new format */
+#define XFS_DIFLAG_IMMUTABLE_BIT 3 /* inode is immutable */
+#define XFS_DIFLAG_APPEND_BIT 4 /* inode is append-only */
+#define XFS_DIFLAG_SYNC_BIT 5 /* inode is written synchronously */
+#define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */
+#define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */
+#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT)
+#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT)
+#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT)
+#define XFS_DIFLAG_IMMUTABLE (1 << XFS_DIFLAG_IMMUTABLE_BIT)
+#define XFS_DIFLAG_APPEND (1 << XFS_DIFLAG_APPEND_BIT)
+#define XFS_DIFLAG_SYNC (1 << XFS_DIFLAG_SYNC_BIT)
+#define XFS_DIFLAG_NOATIME (1 << XFS_DIFLAG_NOATIME_BIT)
+#define XFS_DIFLAG_NODUMP (1 << XFS_DIFLAG_NODUMP_BIT)
#endif /* __XFS_DINODE_H__ */
* There should be a one-to-one correspondence between these flags and the
* XFS_DIFLAG_s.
*/
-#define XFS_XFLAG_REALTIME 0x00000001
-#define XFS_XFLAG_PREALLOC 0x00000002
+#define XFS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */
+#define XFS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */
+#define XFS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */
+#define XFS_XFLAG_APPEND 0x00000010 /* all writes append */
+#define XFS_XFLAG_SYNC 0x00000020 /* all writes synchronous */
+#define XFS_XFLAG_NOATIME 0x00000040 /* do not update access time */
+#define XFS_XFLAG_NODUMP 0x00000080 /* do not include in backups */
#define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
-#define XFS_XFLAG_ALL \
- ( XFS_XFLAG_REALTIME|XFS_XFLAG_PREALLOC|XFS_XFLAG_HASATTR )
-
/*
* Structure for XFS_IOC_GETBMAP.
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
-#ifdef DEBUG
+#if 0
if (agno >= mp->m_sb.sb_agcount) {
xfs_fs_cmn_err(CE_ALERT, mp,
"xfs_dilocate: agno (%d) >= "
ip->i_d.di_dmevmask = 0;
ip->i_d.di_dmstate = 0;
ip->i_d.di_flags = 0;
+ if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) && xfs_inherit_nodump)
+ ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
flags = XFS_ILOG_CORE;
switch (mode & IFMT) {
case IFIFO:
break;
case IFREG:
case IFDIR:
+ if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) && xfs_inherit_sync)
+ ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
case IFLNK:
ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
ip->i_df.if_flags = XFS_IFEXTENTS;
if (IS_RDONLY(inode) &&
(S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
return XFS_ERROR(EROFS);
+
+ if (IS_IMMUTABLE(inode))
+ return XFS_ERROR(EACCES);
}
/*
* Don't update access timestamps on reads if mounted "noatime"
* Throw it away if anyone asks us.
*/
- if (ip->i_mount->m_flags & XFS_MOUNT_NOATIME &&
+ if ((ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) &&
((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG))
== XFS_ICHGTIME_ACC))
return;
/*
* convert di_flags to bs_xflags.
*/
- di_flags=INT_GET(dic->di_flags, arch);
+ di_flags = INT_GET(dic->di_flags, arch);
buf->bs_xflags =
((di_flags & XFS_DIFLAG_REALTIME) ?
XFS_XFLAG_REALTIME : 0) |
((di_flags & XFS_DIFLAG_PREALLOC) ?
XFS_XFLAG_PREALLOC : 0) |
+ ((di_flags & XFS_DIFLAG_IMMUTABLE) ?
+ XFS_XFLAG_IMMUTABLE : 0) |
+ ((di_flags & XFS_DIFLAG_APPEND) ?
+ XFS_XFLAG_APPEND : 0) |
+ ((di_flags & XFS_DIFLAG_SYNC) ?
+ XFS_XFLAG_SYNC : 0) |
+ ((di_flags & XFS_DIFLAG_NOATIME) ?
+ XFS_XFLAG_NOATIME : 0) |
+ ((di_flags & XFS_DIFLAG_NODUMP) ?
+ XFS_XFLAG_NODUMP : 0) |
(XFS_CFORK_Q_ARCH(dic, arch) ?
XFS_XFLAG_HASATTR : 0);
XFS_XFLAG_REALTIME : 0) |
((ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) ?
XFS_XFLAG_PREALLOC : 0) |
+ ((ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) ?
+ XFS_XFLAG_IMMUTABLE : 0) |
+ ((ip->i_d.di_flags & XFS_DIFLAG_APPEND) ?
+ XFS_XFLAG_APPEND : 0) |
+ ((ip->i_d.di_flags & XFS_DIFLAG_SYNC) ?
+ XFS_XFLAG_SYNC : 0) |
+ ((ip->i_d.di_flags & XFS_DIFLAG_NOATIME) ?
+ XFS_XFLAG_NOATIME : 0) |
+ ((ip->i_d.di_flags & XFS_DIFLAG_NODUMP) ?
+ XFS_XFLAG_NODUMP: 0) |
(XFS_IFORK_Q(ip) ?
XFS_XFLAG_HASATTR : 0);
vap->va_extsize = ip->i_d.di_extsize << mp->m_sb.sb_blocklog;
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;
+ }
}
/*
ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
ip->i_iocore.io_flags |= XFS_IOCORE_RT;
}
+ if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
+ ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE;
+ if (vap->va_xflags & XFS_XFLAG_APPEND)
+ ip->i_d.di_flags |= XFS_DIFLAG_APPEND;
+ if (vap->va_xflags & XFS_XFLAG_SYNC)
+ ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+ if (vap->va_xflags & XFS_XFLAG_NOATIME)
+ ip->i_d.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 */
}
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
if ((((ip->i_d.di_mode & IFMT) == IFREG) &&
((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) &&
(ip->i_df.if_flags & XFS_IFEXTENTS)) &&
- (!(ip->i_d.di_flags & XFS_DIFLAG_PREALLOC))) {
+ (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) {
if ((error = xfs_inactive_free_eofblocks(mp, ip)))
return (error);
/* Update linux inode block count after free above */
if ((((ip->i_d.di_mode & IFMT) == IFREG) &&
((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) &&
(ip->i_df.if_flags & XFS_IFEXTENTS)) &&
- (!(ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) ||
+ (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) ||
(ip->i_delayed_blks != 0))) {
if ((error = xfs_inactive_free_eofblocks(mp, ip)))
return (VN_INACTIVE_CACHE);
static char *diflags[] = {
"realtime", /* XFS_DIFLAG_REALTIME */
"prealloc", /* XFS_DIFLAG_PREALLOC */
+ "newrtbm", /* XFS_DIFLAG_NEWRTBM */
+ "immutable", /* XFS_DIFLAG_IMMUTABLE */
+ "append", /* XFS_DIFLAG_APPEND */
+ "sync", /* XFS_DIFLAG_SYNC */
+ "noatime", /* XFS_DIFLAG_NOATIME */
+ "nodump", /* XFS_DIFLAG_NODUMP */
NULL
};