diff options
author | Theodore Ts'o <tytso@mit.edu> | 2019-08-11 16:30:41 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2019-08-11 16:30:41 -0400 |
commit | b0c013e2928d3696ceb6401311dbc1d7fcccd6dd (patch) | |
tree | 673e10bc5de72eab8f375f913df207ccf6a3afea | |
parent | 547b9ad698b434eadca46319cb47e5875b55ef03 (diff) |
ext4: add a new ioctl EXT4_IOC_CLEAR_ES_CACHE
The new ioctl EXT4_IOC_CLEAR_ES_CACHE will force an inode's extent
status cache to be cleared out. This is intended for use for
debugging.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
-rw-r--r-- | fs/ext4/extents_status.c | 28 | ||||
-rw-r--r-- | fs/ext4/extents_status.h | 1 | ||||
-rw-r--r-- | fs/ext4/ioctl.c | 9 |
4 files changed, 40 insertions, 0 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index bf660aa7a9e0..b22f24f1d365 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -649,6 +649,8 @@ enum { | |||
649 | #define EXT4_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY | 649 | #define EXT4_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY |
650 | #define EXT4_IOC_GET_ENCRYPTION_PWSALT FS_IOC_GET_ENCRYPTION_PWSALT | 650 | #define EXT4_IOC_GET_ENCRYPTION_PWSALT FS_IOC_GET_ENCRYPTION_PWSALT |
651 | #define EXT4_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY | 651 | #define EXT4_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY |
652 | /* ioctl codes 19--39 are reserved for fscrypt */ | ||
653 | #define EXT4_IOC_CLEAR_ES_CACHE _IO('f', 40) | ||
652 | 654 | ||
653 | #define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR | 655 | #define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR |
654 | #define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR | 656 | #define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR |
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 7521de2dcf3a..02cc8eb3eb0e 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c | |||
@@ -1374,6 +1374,34 @@ static int es_reclaim_extents(struct ext4_inode_info *ei, int *nr_to_scan) | |||
1374 | return nr_shrunk; | 1374 | return nr_shrunk; |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | /* | ||
1378 | * Called to support EXT4_IOC_CLEAR_ES_CACHE. We can only remove | ||
1379 | * discretionary entries from the extent status cache. (Some entries | ||
1380 | * must be present for proper operations.) | ||
1381 | */ | ||
1382 | void ext4_clear_inode_es(struct inode *inode) | ||
1383 | { | ||
1384 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
1385 | struct extent_status *es; | ||
1386 | struct ext4_es_tree *tree; | ||
1387 | struct rb_node *node; | ||
1388 | |||
1389 | write_lock(&ei->i_es_lock); | ||
1390 | tree = &EXT4_I(inode)->i_es_tree; | ||
1391 | tree->cache_es = NULL; | ||
1392 | node = rb_first(&tree->root); | ||
1393 | while (node) { | ||
1394 | es = rb_entry(node, struct extent_status, rb_node); | ||
1395 | node = rb_next(node); | ||
1396 | if (!ext4_es_is_delayed(es)) { | ||
1397 | rb_erase(&es->rb_node, &tree->root); | ||
1398 | ext4_es_free_extent(inode, es); | ||
1399 | } | ||
1400 | } | ||
1401 | ext4_clear_inode_state(inode, EXT4_STATE_EXT_PRECACHED); | ||
1402 | write_unlock(&ei->i_es_lock); | ||
1403 | } | ||
1404 | |||
1377 | #ifdef ES_DEBUG__ | 1405 | #ifdef ES_DEBUG__ |
1378 | static void ext4_print_pending_tree(struct inode *inode) | 1406 | static void ext4_print_pending_tree(struct inode *inode) |
1379 | { | 1407 | { |
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h index 131a8b7df265..e16785f431e7 100644 --- a/fs/ext4/extents_status.h +++ b/fs/ext4/extents_status.h | |||
@@ -248,5 +248,6 @@ extern unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk, | |||
248 | ext4_lblk_t len); | 248 | ext4_lblk_t len); |
249 | extern void ext4_es_remove_blks(struct inode *inode, ext4_lblk_t lblk, | 249 | extern void ext4_es_remove_blks(struct inode *inode, ext4_lblk_t lblk, |
250 | ext4_lblk_t len); | 250 | ext4_lblk_t len); |
251 | extern void ext4_clear_inode_es(struct inode *inode); | ||
251 | 252 | ||
252 | #endif /* _EXT4_EXTENTS_STATUS_H */ | 253 | #endif /* _EXT4_EXTENTS_STATUS_H */ |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 442f7ef873fc..15b1047878ab 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -1115,6 +1115,14 @@ resizefs_out: | |||
1115 | case EXT4_IOC_GET_ENCRYPTION_POLICY: | 1115 | case EXT4_IOC_GET_ENCRYPTION_POLICY: |
1116 | return fscrypt_ioctl_get_policy(filp, (void __user *)arg); | 1116 | return fscrypt_ioctl_get_policy(filp, (void __user *)arg); |
1117 | 1117 | ||
1118 | case EXT4_IOC_CLEAR_ES_CACHE: | ||
1119 | { | ||
1120 | if (!inode_owner_or_capable(inode)) | ||
1121 | return -EACCES; | ||
1122 | ext4_clear_inode_es(inode); | ||
1123 | return 0; | ||
1124 | } | ||
1125 | |||
1118 | case EXT4_IOC_FSGETXATTR: | 1126 | case EXT4_IOC_FSGETXATTR: |
1119 | { | 1127 | { |
1120 | struct fsxattr fa; | 1128 | struct fsxattr fa; |
@@ -1233,6 +1241,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1233 | case EXT4_IOC_GET_ENCRYPTION_POLICY: | 1241 | case EXT4_IOC_GET_ENCRYPTION_POLICY: |
1234 | case EXT4_IOC_SHUTDOWN: | 1242 | case EXT4_IOC_SHUTDOWN: |
1235 | case FS_IOC_GETFSMAP: | 1243 | case FS_IOC_GETFSMAP: |
1244 | case EXT4_IOC_CLEAR_ES_CACHE: | ||
1236 | break; | 1245 | break; |
1237 | default: | 1246 | default: |
1238 | return -ENOIOCTLCMD; | 1247 | return -ENOIOCTLCMD; |