Commit 57b6451f authored by Nathan Scott's avatar Nathan Scott Committed by Stephen Lord

[XFS] Implement several additional inode flags - immutable, append-only, etc;...

[XFS] Implement several additional inode flags - immutable, append-only, etc; contributed by Ethan Benson.

SGI Modid: 2.5.x-xfs:slinx:158362a
parent 9f001d18
......@@ -59,6 +59,8 @@ xfs_param_t xfs_params = {
.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 },
};
/*
......
......@@ -72,6 +72,13 @@
#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
......@@ -328,6 +335,17 @@ xfs_open_by_handle(
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);
......@@ -429,6 +447,11 @@ xfs_fssetdm_by_handle(
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);
......@@ -514,11 +537,19 @@ xfs_attrmulti_by_handle(
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;
......@@ -566,6 +597,7 @@ xfs_ioc_fsgeometry(
STATIC int
xfs_ioc_xattr(
vnode_t *vp,
xfs_inode_t *ip,
struct file *filp,
unsigned int cmd,
unsigned long arg);
......@@ -648,10 +680,13 @@ xfs_ioctl(
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;
......@@ -837,6 +872,9 @@ xfs_ioc_space(
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);
......@@ -957,9 +995,50 @@ xfs_ioc_fsgeometry(
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)
......@@ -967,6 +1046,8 @@ xfs_ioc_xattr(
struct fsxattr fa;
vattr_t va;
int error;
int attr_flags;
unsigned int flags;
switch (cmd) {
case XFS_IOC_FSGETXATTR: {
......@@ -985,24 +1066,24 @@ xfs_ioc_xattr(
}
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)
......@@ -1017,9 +1098,54 @@ xfs_ioc_xattr(
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;
}
}
......
......@@ -638,6 +638,9 @@ linvfs_setxattr(
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;
......@@ -787,6 +790,9 @@ linvfs_removexattr(
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))
......
......@@ -96,6 +96,8 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
#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)
......
......@@ -187,7 +187,22 @@ xfs_revalidate_inode(
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;
}
......
......@@ -97,6 +97,16 @@ STATIC ctl_table xfs_table[] = {
&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,
......
......@@ -55,6 +55,8 @@ typedef struct xfs_param {
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;
/*
......@@ -73,13 +75,15 @@ typedef struct xfs_param {
*/
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;
......
......@@ -213,6 +213,22 @@ vn_revalidate(
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;
......
......@@ -388,6 +388,8 @@ xfs_acl_allow_set(
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)
......
......@@ -192,6 +192,8 @@ xfs_cap_allow_set(
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;
......
......@@ -471,13 +471,21 @@ xfs_dinode_t *xfs_buf_to_dinode(struct xfs_buf *bp);
* 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__ */
......@@ -69,12 +69,14 @@ struct fsxattr {
* 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.
......
......@@ -1114,7 +1114,7 @@ xfs_dilocate(
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) >= "
......
......@@ -1197,6 +1197,8 @@ xfs_ialloc(
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:
......@@ -1210,6 +1212,8 @@ xfs_ialloc(
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;
......@@ -3500,6 +3504,9 @@ xfs_iaccess(
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);
}
/*
......@@ -3623,7 +3630,7 @@ xfs_ichgtime(xfs_inode_t *ip,
* 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;
......
......@@ -156,13 +156,23 @@ xfs_bulkstat_one(
/*
* 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);
......
......@@ -265,6 +265,16 @@ xfs_getattr(
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;
......@@ -647,6 +657,20 @@ xfs_setattr(
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;
}
}
/*
......@@ -832,6 +856,16 @@ xfs_setattr(
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);
......@@ -1634,7 +1668,7 @@ xfs_release(
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 */
......@@ -1709,7 +1743,7 @@ xfs_inactive(
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);
......
......@@ -3021,6 +3021,12 @@ xfs_prdinode_core(xfs_dinode_core_t *dip, int convert)
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
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment