[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20100701235738.19035.21536.stgit@warthog.procyon.org.uk>
Date: Fri, 02 Jul 2010 00:57:38 +0100
From: David Howells <dhowells@...hat.com>
To: linux-fsdevel@...r.kernel.org
Cc: dhowells@...hat.com, linux-cifs@...r.kernel.org,
linux-kernel@...r.kernel.org, samba-technical@...ts.samba.org,
linux-ext4@...r.kernel.org
Subject: [PATCH 3/3] xstat: Implement a requestable extra result to procure
some inode flags [ver #4]
[This is, for the moment, to be considered an example. Do we actually want to
export these flags? Should they be a full member of struct xstat?]
Allow an extra result to be requested that makes available some inode flags,
along the lines of BSD's st_flags and Ext2/3/4's inode flags. This is
requested by setting XSTAT_REQUEST_INODE_FLAGS in the request_mask. If the
filesystem supports it for that file, then this will be set in result_mask and
16 bytes of information will be appended to the xstat buffer, if sufficient
buffer space is available.
The extra result is laid out according to the following structure:
struct xstat_inode_flags {
unsigned long long st_flags;
unsigned long long st_supported_flags;
};
where the filesystem indicates the flags it supports for that file and the
flags that are set on that file. The structure is of length:
XSTAT_LENGTH_INODE_FLAGS
The flags come in three sets:
(1) User settable flags (to be consistent with the BSD st_flags field):
UF_NODUMP Do not dump this file.
UF_IMMUTABLE This file is immutable.
UF_APPEND This file is append-only.
UF_OPAQUE This directory is opaque (unionfs).
UF_NOUNLINK This file can't be removed or renamed.
UF_COMPRESSED This file is compressed.
UF_HIDDEN This file shouldn't be displayed in a GUI.
The UF_SETTABLE constant is the union of the above flags.
(2) Superuser settable flags (to be consistent with the BSD st_flags field):
SF_ARCHIVED This file has been archived.
SF_IMMUTABLE This file is immutable.
SF_APPEND This file is append-only.
SF_NOUNLINK This file can't be removed or renamed.
SF_HIDDEN This file is a snapshot inode.
The SF_SETTABLE constant is the union of the above flags.
(3) Linux-specific flags:
XSTAT_LF_MAGIC_FILE Magic file, such as found in procfs and sysfs.
XSTAT_LF_SYNC File is written synchronously.
XSTAT_LF_NOATIME Atime is not updated on this file.
XSTAT_LF_JOURNALLED_DATA Data modifications to this file are journalled.
XSTAT_LF_ENCRYPTED This file is encrypted.
XSTAT_LF_SYSTEM This file is a system file (FAT/NTFS/CIFS).
XSTAT_LF_TEMPORARY This file is a temporary file (NTFS/CIFS).
XSTAT_LF_OFFLINE file is currently unavailable (CIFS).
The Ext4 filesystem has been modified to map certain Ext4 inode flags to the
above:
EXT4 FLAG MAPPED TO
======================= =======================================
EXT4_COMPR_FL UF_COMPRESSED
EXT4_SYNC_FL XSTAT_LF_SYNC
EXT4_IMMUTABLE_FL UF_IMMUTABLE and SF_IMMUTABLE
EXT4_APPEND_FL UF_APPEND and SF_APPEND
EXT4_NODUMP_FL UF_NODUMP
EXT4_NOATIME_FL XSTAT_LF_NOATIME
EXT4_JOURNAL_DATA_FL XSTAT_LF_JOURNALLED_DATA
EXT4_DIRSYNC_FL XSTAT_LF_SYNC (directories only)
With this patch applied, the test program given in the patch that introduced
the xstat() syscalls now does this:
[root@...romeda ~]# chattr +ia /var/cache/fscache/cull_atimes
[root@...romeda ~]# lsattr /var/cache/fscache/cull_atimes
----ia-------e- /var/cache/fscache/cull_atimes
[root@...romeda ~]# /tmp/xstat /var/cache/fscache/cull_atimes
xstat(/var/cache/fscache/cull_atimes) = 168
results=5fef
Size: 78088 Blocks: 168 IO Block: 4096 regular file
Device: 08:06 Inode: 13 Links: 1
Access: (0600/-rw-------) Uid: 0
Gid: 0
Access: 2010-06-29 18:17:41.092290108+0100
Modify: 2010-06-25 17:25:53.320261493+0100
Change: 2010-07-02 00:46:51.278803967+0100
Create: 2010-06-25 15:17:39.711172889+0100
Inode version: f585ab73h
0098: 0000000000060006 0000000e00060027
The extra results are hex dumped at the end in 64-bit chunks. As can be seen
above, st_flags=0x0000000000060006 and st_supported_flags=0000000e00060027.
That's showing that the file now has [SU]F_IMMUTABLE and [SU]F_APPEND enabled.
Note also that XSTAT_REQUEST_INODE_FLAGS (0x4000) is present in the result_mask
value (0x5fef) returned to userspace, and the amount of data returned by
xstat() has increased from 152 to 168 as appropriate for 16 bytes of extra
data.
Signed-off-by: David Howells <dhowells@...hat.com>
---
fs/ext4/ext4.h | 2 ++
fs/ext4/file.c | 1 +
fs/ext4/inode.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
fs/ext4/namei.c | 2 ++
fs/ext4/symlink.c | 2 ++
include/linux/stat.h | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
6 files changed, 103 insertions(+), 1 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 96823f3..26b8dd6 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1573,6 +1573,8 @@ extern int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat);
extern int ext4_file_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat);
+extern int ext4_getattr_extra(struct vfsmount *, struct dentry *,
+ struct xstat_extra_result *);
extern void ext4_delete_inode(struct inode *);
extern int ext4_sync_inode(handle_t *, struct inode *);
extern void ext4_dirty_inode(struct inode *);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 18c29ab..657ffa0 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -151,6 +151,7 @@ const struct inode_operations ext4_file_inode_operations = {
.truncate = ext4_truncate,
.setattr = ext4_setattr,
.getattr = ext4_file_getattr,
+ .getattr_extra = ext4_getattr_extra,
#ifdef CONFIG_EXT4_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index f9a730a..efa17d6 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5595,6 +5595,56 @@ int ext4_file_getattr(struct vfsmount *mnt, struct dentry *dentry,
return 0;
}
+int ext4_getattr_inode_flags(struct inode *inode,
+ struct xstat_extra_result *extra)
+{
+ struct ext4_inode_info *ei = EXT4_I(inode);
+ struct xstat_inode_flags xif = { 0, 0 };
+
+#define _(FL, ST) \
+ xif.st_supported_flags |= ST; \
+ if (ei->i_flags & FL) \
+ xif.st_flags |= ST;
+
+ _(EXT4_COMPR_FL, UF_COMPRESSED);
+ _(EXT4_SYNC_FL, XSTAT_LF_SYNC);
+ _(EXT4_IMMUTABLE_FL, UF_IMMUTABLE | SF_IMMUTABLE);
+ _(EXT4_APPEND_FL, UF_APPEND | SF_APPEND);
+ _(EXT4_NODUMP_FL, UF_NODUMP);
+ _(EXT4_NOATIME_FL, XSTAT_LF_NOATIME);
+ _(EXT4_JOURNAL_DATA_FL, XSTAT_LF_JOURNALLED_DATA);
+
+ if (S_ISDIR(ei->vfs_inode.i_mode))
+ _(EXT4_DIRSYNC_FL, XSTAT_LF_SYNC);
+
+ return extra->pass_result(extra, ilog2(XSTAT_REQUEST_INODE_FLAGS),
+ &xif, sizeof(xif));
+}
+
+int ext4_getattr_extra(struct vfsmount *mnt, struct dentry *dentry,
+ struct xstat_extra_result *extra)
+{
+ struct inode *inode = dentry->d_inode;
+ u64 request_mask = extra->request_mask;
+ int request, ret;
+
+ do {
+ request = __ffs64(request_mask);
+ request_mask &= ~(1ULL << request);
+
+ switch (request) {
+ case ilog2(XSTAT_REQUEST_INODE_FLAGS):
+ ret = ext4_getattr_inode_flags(inode, extra);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ } while (ret == 0 && request_mask);
+ return ret;
+}
+
static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
int chunk)
{
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 0f776c7..3c37b3f 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2543,6 +2543,7 @@ const struct inode_operations ext4_dir_inode_operations = {
.rename = ext4_rename,
.setattr = ext4_setattr,
.getattr = ext4_getattr,
+ .getattr_extra = ext4_getattr_extra,
#ifdef CONFIG_EXT4_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
@@ -2556,6 +2557,7 @@ const struct inode_operations ext4_dir_inode_operations = {
const struct inode_operations ext4_special_inode_operations = {
.setattr = ext4_setattr,
.getattr = ext4_getattr,
+ .getattr_extra = ext4_getattr_extra,
#ifdef CONFIG_EXT4_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index d8fe7fb..8c206b2 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -36,6 +36,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
.put_link = page_put_link,
.setattr = ext4_setattr,
.getattr = ext4_getattr,
+ .getattr_extra = ext4_getattr_extra,
#ifdef CONFIG_EXT4_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
@@ -49,6 +50,7 @@ const struct inode_operations ext4_fast_symlink_inode_operations = {
.follow_link = ext4_follow_link,
.setattr = ext4_setattr,
.getattr = ext4_getattr,
+ .getattr_extra = ext4_getattr_extra,
#ifdef CONFIG_EXT4_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 9e27f88..4c87878 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -107,7 +107,8 @@ struct xstat_parameters {
#define XSTAT_REQUEST_GEN 0x00001000ULL /* want/got st_gen */
#define XSTAT_REQUEST_DATA_VERSION 0x00002000ULL /* want/got st_data_version */
#define XSTAT_REQUEST__EXTENDED_STATS 0x00003fffULL /* the stuff in the xstat struct */
-#define XSTAT_REQUEST__ALL_STATS 0x00003fffULL /* the defined set of requestables */
+#define XSTAT_REQUEST_INODE_FLAGS 0x00004000ULL /* want/got xstat_inode_flags */
+#define XSTAT_REQUEST__ALL_STATS 0x00007fffULL /* the defined set of requestables */
#define XSTAT_REQUEST__EXTRA_STATS (XSTAT_REQUEST__ALL_STATS & ~XSTAT_REQUEST__EXTENDED_STATS)
};
@@ -140,6 +141,50 @@ struct xstat {
unsigned long long st_extra_results[0]; /* extra requested results */
};
+/*
+ * Extra result field for inode flags (XSTAT_REQUEST_INODE_FLAGS)
+ */
+struct xstat_inode_flags {
+ /* Flags set on the file
+ * - the LSW matches the BSD st_flags
+ * - the MSW are Linux-specific
+ */
+ unsigned long long st_flags;
+ /* st_flags that users can set */
+#define UF_SETTABLE 0x0000ffff
+#define UF_NODUMP 0x00000001 /* do not dump */
+#define UF_IMMUTABLE 0x00000002 /* immutable */
+#define UF_APPEND 0x00000004 /* append-only */
+#define UF_OPAQUE 0x00000008 /* directory is opaque (unionfs) */
+#define UF_NOUNLINK 0x00000010 /* can't be removed or renamed */
+#define UF_COMPRESSED 0x00000020 /* file is compressed */
+#define UF_HIDDEN 0x00008000 /* file shouldn't be displayed in a GUI */
+
+ /* st_flags that only root can set */
+#define SF_SETTABLE 0xffff0000
+#define SF_ARCHIVED 0x00010000 /* archived */
+#define SF_IMMUTABLE 0x00020000 /* immutable */
+#define SF_APPEND 0x00040000 /* append-only */
+#define SF_NOUNLINK 0x00100000 /* can't be removed or renamed */
+#define SF_SNAPSHOT 0x00200000 /* snapshot inode */
+
+ /* Linux-specific st_flags */
+#define XSTAT_LF_MAGIC_FILE (1ULL << 32) /* magic file, such as /proc/? and /sys/? */
+#define XSTAT_LF_SYNC (1ULL << 33) /* file is written synchronously */
+#define XSTAT_LF_NOATIME (1ULL << 34) /* atime is not updated on file */
+#define XSTAT_LF_JOURNALLED_DATA (1ULL << 35) /* data modifications to file are journalled */
+#define XSTAT_LF_ENCRYPTED (1ULL << 36) /* file is encrypted */
+#define XSTAT_LF_SYSTEM (1ULL << 37) /* system file */
+#define XSTAT_LF_TEMPORARY (1ULL << 38) /* temporary file */
+#define XSTAT_LF_OFFLINE (1ULL << 39) /* file is currently unavailable */
+
+ /* Which st_flags are actually supported by this filesystem for this
+ * file */
+ unsigned long long st_supported_flags;
+};
+#define XSTAT_LENGTH_INODE_FLAGS (sizeof(struct xstat_inode_flags))
+
+
#ifdef __KERNEL__
#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists