I-node Flags (ext2 Extended File Attributes)

Some Linux file systems allow various i-node flags to be set on files and directories. This feature is a nonstandard Linux extension.

Note

The modern BSDs provide a similar feature to i-node flags in the form of file flags set using chflags(1) and chflags(2).

The first Linux file system to support i-node flags was ext2, and these flags are sometimes referred to as ext2 extended file attributes. Subsequently, support for i-node flags has been added on other file systems, including Btrfs, ext3, ext4, Reiserfs (since Linux 2.4.19), XFS (since Linux 2.4.25 and 2.6), and JFS (since Linux 2.6.17).

Note

The range of i-node flags supported varies somewhat across file systems. In order to use i-node flags on a Reiserfs file system, we must use the mount -o attrs option when mounting the file system.

From the shell, i-node flags can be set and viewed using the chattr and lsattr commands, as shown in the following example:

$ lsattr myfile
-------- myfile
$ chattr +ai myfile               Turn on Append Only and Immutable flags
$ lsattr myfile
----ia-- myfile

Within a program, i-node flags can be retrieved and modified using the ioctl() system call, as detailed shortly.

I-node flags can be set on both regular files and directories. Most i-node flags are intended for use with regular files, although some of them also (or only) have meaning for directories. Table 15-6 summarizes the range of available i-node flags, showing the corresponding flag name (defined in <linux/fs.h>) that is used from programs in ioctl() calls, and the option letter that is used with the chattr command.

Note

Before Linux 2.6.19, the FS_* constants shown in Table 15-6 were not defined in <linux/fs.h>. Instead, there was a set of file system–specific header files that defined file system-specific constant names, all with the same value. Thus, ext2 had EXT2_APPEND_FL, defined in <linux/ext2_fs.h>; Reiserfs had REISERFS_APPEND_FL, defined with the same value in <linux/reiser_fs.h>; and so on. Since each of the header files defines the corresponding constants with the same value, on older systems that don’t provide the definitions in <linux/fs.h>, it is possible to include any of the header files and use the file system–specific names.

Table 15-6. I-node flags

Constant

chattr option

Purpose

FS_APPEND_FL

a

Append only (privilege required)

FS_COMPR_FL

c

Enable file compression (not implemented)

FS_DIRSYNC_FL

D

Synchronous directory updates (since Linux 2.6)

FS_IMMUTABLE_FL

i

Immutable (privilege required)

FS_JOURNAL_DATA_FL

j

Enable data journaling (privilege required)

FS_NOATIME_FL

A

Don’t update file last access time

FS_NODUMP_FL

d

No dump

FS_NOTAIL_FL

t

No tail packing

FS_SECRM_FL

s

Secure deletion (not implemented)

FS_SYNC_FL

S

Synchronous file (and directory) updates

FS_TOPDIR_FL

T

Treat as top-level directory for Orlov (since Linux 2.6)

FS_UNRM_FL

u

File can be undeleted (not implemented)

The various FL_* flags and their meanings are as follows:

FS_APPEND_FL

The file can be opened for writing only if the O_APPEND flag is specified (thus forcing all file updates to append to the end of the file). This flag could be used for a log file, for example. Only privileged (CAP_LINUX_IMMUTABLE) processes can set this flag.

FS_COMPR_FL

Store the file on disk in a compressed format. This feature is not implemented as a standard part of any of the major native Linux file systems. (There are packages that implement this feature for ext2 and ext3.) Given the low cost of disk storage, the CPU overhead involved in compression and decompression, and the fact that compressing a file means that it is no longer a simple matter to randomly access the file’s contents (via lseek()), file compression is undesirable for many applications.

FS_DIRSYNC_FL (since Linux 2.6)

Make directory updates (e.g., open(pathname, O_CREAT), link(), unlink(), and mkdir()) synchronous. This is analogous to the synchronous file update mechanism described in Section 13.3. As with synchronous file updates, there is a performance impact associated with synchronous directory updates. This setting can be applied only to directories. (The MS_DIRSYNC mount flag described in Mounting a File System: mount() provides similar functionality, but on a per-mount basis.)

FS_IMMUTABLE_FL

Make the file immutable. File data can’t be updated (write() and truncate()) and metadata changes are prevented (e.g., chmod(), chown(), unlink(), link(), rename(), rmdir(), utime(), setxattr(), and removexattr()). Only privileged (CAP_LINUX_IMMUTABLE) processes can set this flag for a file. When this flag is set, even a privileged process can’t change the file contents or metadata.

FS_JOURNAL_DATA_FL

Enable journaling of data. This flag is supported only on the ext3 and ext4 file systems. These file systems provide three levels of journaling: journal, ordered, and writeback. All modes journal updates to file metadata, but the journal mode additionally journals updates to file data. On a file system that is journaling in ordered or writeback mode, a privileged (CAP_SYS_RESOURCE) process can enable journaling of data updates on a per-file basis by setting this flag. (The mount(8) manual page describes the difference between the ordered and writeback modes.)

FS_NOATIME_FL

Don’t update the file last access time when the file is accessed. This eliminates the need to update the file’s i-node each time the file is accessed, thus improving I/O performance (see the description of the MS_NOATIME flag in Mounting a File System: mount()).

FS_NODUMP_FL

Don’t include this file in backups made using dump(8). The effect of this flag is dependent on the -h option described in the dump(8) manual page.

FS_NOTAIL_FL

Disable tail packing. This flag is supported only on the Reiserfs file system. It disables the Reiserfs tail-packing feature, which tries to pack small files (and the final fragment of larger files) into the same disk block as the file metadata. Tail packing can also be disabled for an entire Reiserfs file system by mounting it with the mount -o notail option.

FS_SECRM_FL

Delete the file securely. The intended purpose of this unimplemented feature is that, when removed, a file is securely deleted, meaning that it is first overwritten to prevent a disk-scanning program from reading or re-creating it. (The issue of truly secure deletion is rather complex: it can actually require multiple writes on magnetic media to securely erase previously recorded data; see [Gutmann, 1996].)

FS_SYNC_FL

Make file updates synchronous. When applied to files, this flag causes writes to the file to be synchronous (as though the O_SYNC flag was specified on all opens of this file). When applied to a directory, this flag has the same effect as the synchronous directory updates flag described above.

FS_TOPDIR_FL (since Linux 2.6)

This marks a directory for special treatment under the Orlov block-allocation strategy. The Orlov strategy is a BSD-inspired modification of the ext2 block-allocation strategy that tries to improve the chances that related files (e.g., the files within a single directory) are placed close to each other on disk, which can improve disk seek times. For details, see [Corbet, 2002] and [Kumar, et al. 2008]. FS_TOPDIR_FL has an effect only for ext2 and its descendants, ext3 and ext4.

FS_UNRM_FL

Allow this file to be recovered (undeleted) if it is deleted. This feature is not implemented, since it is possible to implement file-recovery mechanisms outside the kernel.

Generally, when i-node flags are set on a directory, they are automatically inherited by new files and subdirectories created in that directory. There are exceptions to this rule:

Within a program, i-node flags can be retrieved and modified using the ioctl() FS_IOC_GETFLAGS and FS_IOC_SETFLAGS operations. (These constants are defined in <linux/fs.h>.) The following code shows how to enable the FS_NOATIME_FL flag on the file referred to by the open file descriptor fd:

int attr;

if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == -1)    /* Fetch current flags */
    errExit("ioctl");
attr |= FS_NOATIME_FL;
if (ioctl(fd, FS_IOC_SETFLAGS, &attr) == -1)    /* Update flags */
    errExit("ioctl");

In order to change the i-node flags of a file, either the effective user ID of the process must match the user ID (owner) of the file, or the process must be privileged (CAP_FOWNER). (To be strictly accurate, on Linux, for an unprivileged process it is the process’s file-system user ID, rather than its effective user ID, that must match the user ID of the file, as described in Section 9.5.)