Add FALLOC_FL_NO_HIDE_STALE
Port of http://www.spinics.net/lists/linux-ext4/msg32702.html
to the Mindspeed 3.2.26 kernel.
HOWEVER: we allow KEEP_SIZE and NO_HIDE_STALE to be used at
the same time, as we need to know the actual size of the
video not the fallocated size. From the link above:
"Also note that I restrict the combination of NO_HIDE_STALE && KEEP_SIZE
since it causes e2fsck to complain --- and if you're trying to avoid fs
metadata I/O, you want to avoid the extra i_size update anyway, so it's
not worth trying to make this work w/o causing e2fsck complaints."
We intend to modify e2fsck in our tree to know about this combination
and not complain.
Change-Id: Ic50ab699f32b6d383ef2062beebc8b238ee7e391
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 8cb184c..0084ef9 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1205,6 +1205,9 @@
unsigned long s_mb_last_group;
unsigned long s_mb_last_start;
+ /* gid that's allowed to see stale data via falloc flag. */
+ gid_t no_hide_stale_gid;
+
/* stats for buddy allocator */
atomic_t s_bal_reqs; /* number of reqs with len > 1 */
atomic_t s_bal_success; /* we found long enough chunks */
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 54f2bdc..8a4f6b2 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4299,6 +4299,7 @@
int retries = 0;
int flags;
struct ext4_map_blocks map;
+ struct ext4_sb_info *sbi;
unsigned int credits, blkbits = inode->i_blkbits;
/*
@@ -4309,12 +4310,23 @@
return -EOPNOTSUPP;
/* Return error if mode is not supported */
- if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+ if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_NO_HIDE_STALE))
return -EOPNOTSUPP;
if (mode & FALLOC_FL_PUNCH_HOLE)
return ext4_punch_hole(file, offset, len);
+ sbi = EXT4_SB(inode->i_sb);
+ /* Must have RAWIO to see stale data. */
+ if ((mode & FALLOC_FL_NO_HIDE_STALE) &&
+ !in_egroup_p(sbi->no_hide_stale_gid))
+ return -EACCES;
+
+ /* preallocation to directories is currently not supported */
+ if (S_ISDIR(inode->i_mode))
+ return -ENODEV;
+
trace_ext4_fallocate_enter(inode, offset, len, mode);
map.m_lblk = offset >> blkbits;
/*
@@ -4353,6 +4365,8 @@
ret = PTR_ERR(handle);
break;
}
+ if (mode & FALLOC_FL_NO_HIDE_STALE)
+ flags &= ~EXT4_GET_BLOCKS_UNINIT_EXT;
ret = ext4_map_blocks(handle, inode, &map, flags);
if (ret <= 0) {
#ifdef EXT4FS_DEBUG
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 0a6eeff..4e99e1d 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1161,6 +1161,9 @@
seq_printf(seq, ",init_itable=%u",
(unsigned) sbi->s_li_wait_mult);
+ if (sbi->no_hide_stale_gid != -1)
+ seq_printf(seq, ",nohide_stale_gid=%u", sbi->no_hide_stale_gid);
+
ext4_show_quota_options(seq, sb);
return 0;
@@ -1335,6 +1338,7 @@
Opt_inode_readahead_blks, Opt_journal_ioprio,
Opt_dioread_nolock, Opt_dioread_lock,
Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
+ Opt_nohide_stale_gid,
};
static const match_table_t tokens = {
@@ -1410,6 +1414,7 @@
{Opt_init_itable, "init_itable=%u"},
{Opt_init_itable, "init_itable"},
{Opt_noinit_itable, "noinit_itable"},
+ {Opt_nohide_stale_gid, "nohide_stale_gid=%u"},
{Opt_err, NULL},
};
@@ -1903,6 +1908,12 @@
return 0;
sbi->s_li_wait_mult = option;
break;
+ case Opt_nohide_stale_gid:
+ if (match_int(&args[0], &option))
+ return 0;
+ /* -1 for disabled, otherwise it's valid. */
+ sbi->no_hide_stale_gid = option;
+ break;
case Opt_noinit_itable:
clear_opt(sb, INIT_INODE_TABLE);
break;
@@ -3321,6 +3332,9 @@
sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
+ /* Default to having no-hide-stale disabled. */
+ sbi->no_hide_stale_gid = -1;
+
if ((def_mount_opts & EXT4_DEFM_NOBARRIER) == 0)
set_opt(sb, BARRIER);
diff --git a/fs/open.c b/fs/open.c
index e2b5d51..15e5192 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -223,7 +223,9 @@
return -EINVAL;
/* Return error if mode is not supported */
- if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+ if (mode & ~(FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_NO_HIDE_STALE))
return -EOPNOTSUPP;
/* Punch hole must have keep size set */
diff --git a/include/linux/falloc.h b/include/linux/falloc.h
index 73e0b62..a2489ac 100644
--- a/include/linux/falloc.h
+++ b/include/linux/falloc.h
@@ -3,6 +3,7 @@
#define FALLOC_FL_KEEP_SIZE 0x01 /* default is extend size */
#define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */
+#define FALLOC_FL_NO_HIDE_STALE 0x04 /* default is hide stale data */
#ifdef __KERNEL__