Well, this is an interesting question.
Unfortunately, even LSM does not help here. As a possible solution, I recommend using the address_space_operations tables and the hook writepage function. For example, see ext3_writeback_aops :
1984 static const struct address_space_operations ext3_writeback_aops = { 1985 .readpage = ext3_readpage, 1986 .readpages = ext3_readpages, 1987 .writepage = ext3_writeback_writepage, 1988 .write_begin = ext3_write_begin, 1989 .write_end = ext3_writeback_write_end, 1990 .bmap = ext3_bmap, 1991 .invalidatepage = ext3_invalidatepage, 1992 .releasepage = ext3_releasepage, 1993 .direct_IO = ext3_direct_IO, 1994 .migratepage = buffer_migrate_page, 1995 .is_partially_uptodate = block_is_partially_uptodate, 1996 .error_remove_page = generic_error_remove_page, 1997 };
So, in the case of the ext3 file system, we need to find this structure in memory and replace the writepage pointer to point to our_writepage wrapper. Also note that this table is in read-only memory and you need to handle it correctly.
EDIT:
With LSM, you can connect inode to open work and replace inode->i_mapping->a_ops in place.
source share