f2fs: avoid value overflow in showing current status
Subsystems (2)
Jaegeuk Kim
maintainerPATCH 1/18 f2fs: avoid value overflow in showing current status
This patch fixes overflow when do cat /sys/kernel/debug/f2fs/status. If a section is relatively large, dist value can be overflowed.
--- fs/f2fs/debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/f2fs/debug.c +2 -1
@@ -94,7 +94,8 @@ static void update_general_status(struct f2fs_sb_info *sbi)static void update_sit_info (struct f2fs_sb_info *sbi) {struct f2fs_stat_info *si =F2FS_STAT (sbi); -unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist; +unsigned long long blks_per_sec, hblks_per_sec, total_vblocks; +unsigned long long bimodal, dist;unsigned int segno, vblocks;int ndirty =0 ;
Signature · 1 line
2.1.1
Jaegeuk Kim
maintainerPATCH 2/18 f2fs: report unwritten area in f2fs_fiemap
This patch slightly changes f2fs_fiemap function to report unwritten area.
--- fs/f2fs/data.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- fs/f2fs/f2fs.h | 4 +- 2 files changed, 117 insertions(+), 4 deletions(-)
fs/f2fs/data.c +114 -3
@@ -1241,6 +1241,8 @@ static int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,if (dn.data_blkaddr !=NULL_ADDR ) { map->m_flags =F2FS_MAP_MAPPED ; map->m_pblk = dn.data_blkaddr; +if (dn.data_blkaddr ==NEW_ADDR ) + map->m_flags |=F2FS_MAP_UNWRITTEN ; }else if (create) { err =__allocate_data_block (&dn);if (err)
@@ -1288,7 +1290,10 @@ get_next: blkaddr = dn.data_blkaddr; }/* Give more consecutive addresses for the readahead */ -if (map->m_pblk !=NEW_ADDR && blkaddr == (map->m_pblk + ofs)) { +if ((map->m_pblk !=NEW_ADDR && + blkaddr == (map->m_pblk + ofs)) || + (map->m_pblk ==NEW_ADDR && + blkaddr ==NEW_ADDR )) { ofs++; dn.ofs_in_node++; pgofs++;
@@ -1339,11 +1344,117 @@ static int get_data_block_fiemap(struct inode *inode, sector_t iblock,return __get_data_block (inode, iblock, bh_result, create, true); } +static inline sector_t logical_to_blk (struct inode *inode,loff_t offset) +{ +return (offset >> inode->i_blkbits); +} + +static inline loff_t blk_to_logical (struct inode *inode,sector_t blk) +{ +return (blk << inode->i_blkbits); +} +int f2fs_fiemap (struct inode *inode,struct fiemap_extent_info *fieinfo,u64 start,u64 len) { -return generic_block_fiemap (inode, fieinfo, - start, len, get_data_block_fiemap); +struct buffer_head map_bh; +sector_t start_blk, last_blk; +loff_t isize =i_size_read (inode); +u64 logical =0 , phys =0 , size =0 ; +u32 flags =0 ; +bool past_eof = false, whole_file = false; +int ret =0 ; + + ret =fiemap_check_flags (fieinfo,FIEMAP_FLAG_SYNC ); +if (ret) +return ret; + +mutex_lock (&inode->i_mutex); + +if (len >= isize) { + whole_file = true; + len = isize; + } + +if (logical_to_blk (inode, len) ==0 ) + len =blk_to_logical (inode,1 ); + + start_blk =logical_to_blk (inode, start); + last_blk =logical_to_blk (inode, start + len -1 ); +next: +memset (&map_bh,0 ,sizeof (struct buffer_head )); + map_bh.b_size = len; + + ret =get_data_block_fiemap (inode, start_blk, &map_bh,0 ); +if (ret) + goto out; + +/* HOLE */ +if (!buffer_mapped (&map_bh)) { + start_blk++; + +if (!past_eof &&blk_to_logical (inode, start_blk) >= isize) + past_eof =1 ; + +if (past_eof && size) { + flags |=FIEMAP_EXTENT_LAST ; + ret =fiemap_fill_next_extent (fieinfo, logical, + phys, size, flags); + }else if (size) { + ret =fiemap_fill_next_extent (fieinfo, logical, + phys, size, flags); + size =0 ; + } + +/* if we have holes up to/past EOF then we're done */ +if (start_blk > last_blk || past_eof || ret) + goto out; + }else { +if (start_blk > last_blk && !whole_file) { + ret =fiemap_fill_next_extent (fieinfo, logical, + phys, size, flags); + goto out; + } + +/* +* if size != 0 then we know we already have an extent +* to add, so add it. +*/ +if (size) { + ret =fiemap_fill_next_extent (fieinfo, logical, + phys, size, flags); +if (ret) + goto out; + } + + logical =blk_to_logical (inode, start_blk); + phys =blk_to_logical (inode, map_bh.b_blocknr); + size = map_bh.b_size; + flags =0 ; +if (buffer_unwritten (&map_bh)) + flags =FIEMAP_EXTENT_UNWRITTEN ; + + start_blk +=logical_to_blk (inode, size); + +/* +* If we are past the EOF, then we need to make sure as +* soon as we find a hole that the last extent we found +* is marked with FIEMAP_EXTENT_LAST +*/ +if (!past_eof && logical + size >= isize) + past_eof = true; + } +cond_resched (); +if (fatal_signal_pending (current)) + ret = -EINTR ; +else + goto next; +out: +if (ret ==1 ) + ret =0 ; + +mutex_unlock (&inode->i_mutex); +return ret; }/*
fs/f2fs/f2fs.h +3 -1
@@ -330,7 +330,9 @@ struct extent_tree {*/ #define F2FS_MAP_NEW (1 << BH_New)#define F2FS_MAP_MAPPED (1 << BH_Mapped) -#define F2FS_MAP_FLAGS (F2FS_MAP_NEW | F2FS_MAP_MAPPED) +#define F2FS_MAP_UNWRITTEN (1 << BH_Unwritten) +#define F2FS_MAP_FLAGS (F2FS_MAP_NEW | F2FS_MAP_MAPPED |\ + F2FS_MAP_UNWRITTEN)struct f2fs_map_blocks {block_t m_pblk;
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 3/18 f2fs crypto: declare some definitions for f2fs encryption feature
In reply to Jaegeuk KimThis definitions will be used by inode and superblock for encyption.
--- fs/f2fs/f2fs.h | 54 ++++++++++++++++++ fs/f2fs/f2fs_crypto.h | 149 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/f2fs_fs.h | 4 +- 3 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 fs/f2fs/f2fs_crypto.h
fs/f2fs/f2fs.h +54 -0
@@ -70,6 +70,8 @@ struct f2fs_mount_info {unsigned int opt; }; +#define F2FS_FEATURE_ENCRYPT 0x0001 +#define F2FS_HAS_FEATURE (sb, mask) \ ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)#define F2FS_SET_FEATURE (sb, mask) \
@@ -346,6 +348,7 @@ struct f2fs_map_blocks {*/ #define FADVISE_COLD_BIT 0x01#define FADVISE_LOST_PINO_BIT 0x02 +#define FADVISE_ENCRYPT_BIT 0x04#define file_is_cold (inode) is_file(inode, FADVISE_COLD_BIT)#define file_wrong_pino (inode) is_file(inode, FADVISE_LOST_PINO_BIT)
@@ -353,6 +356,16 @@ struct f2fs_map_blocks {#define file_lost_pino (inode) set_file(inode, FADVISE_LOST_PINO_BIT)#define file_clear_cold (inode) clear_file(inode, FADVISE_COLD_BIT)#define file_got_pino (inode) clear_file(inode, FADVISE_LOST_PINO_BIT) +#define file_is_encrypt (inode) is_file(inode, FADVISE_ENCRYPT_BIT) +#define file_set_encrypt (inode) set_file(inode, FADVISE_ENCRYPT_BIT) +#define file_clear_encrypt (inode) clear_file(inode, FADVISE_ENCRYPT_BIT) + +/* Encryption algorithms */ +#define F2FS_ENCRYPTION_MODE_INVALID 0 +#define F2FS_ENCRYPTION_MODE_AES_256_XTS 1 +#define F2FS_ENCRYPTION_MODE_AES_256_GCM 2 +#define F2FS_ENCRYPTION_MODE_AES_256_CBC 3 +#define F2FS_ENCRYPTION_MODE_AES_256_CTS 4#define DEF_DIR_LEVEL 0
@@ -380,6 +393,11 @@ struct f2fs_inode_info {struct radix_tree_root inmem_root;/* radix tree for inmem pages */ struct list_head inmem_pages;/* inmemory pages managed by f2fs */ struct mutex inmem_lock;/* lock for inmemory pages */ + +#ifdef CONFIG_F2FS_FS_ENCRYPTION +/* Encryption params */ +struct f2fs_crypt_info *i_crypt_info; +#endif }; static inline void get_extent_info(struct extent_info *ext,
@@ -1891,4 +1909,40 @@ void f2fs_delete_inline_entry(struct f2fs_dir_entry *, struct page *, struct inode *, struct inode *);bool f2fs_empty_inline_dir (struct inode *);int f2fs_read_inline_dir (struct file *,struct dir_context *); + +/* +* crypto support +*/ +static inline int f2fs_encrypted_inode (struct inode *inode) +{ +#ifdef CONFIG_F2FS_FS_ENCRYPTION +return file_is_encrypt (inode); +#else +return 0 ; +#endif +} + +static inline void f2fs_set_encrypted_inode (struct inode *inode) +{ +#ifdef CONFIG_F2FS_FS_ENCRYPTION +file_set_encrypt (inode); +#endif +} + +static inline bool f2fs_bio_encrypted (struct bio *bio) +{ +#ifdef CONFIG_F2FS_FS_ENCRYPTION +return unlikely (bio->bi_private !=NULL ); +#else +return false; +#endif +} + +static inline int f2fs_sb_has_crypto (struct super_block *sb) +{ +#ifdef CONFIG_F2FS_FS_ENCRYPTION +return F2FS_HAS_FEATURE (sb,F2FS_FEATURE_ENCRYPT ); +#else +return 0 ; +#endif #endif
fs/f2fs/f2fs_crypto.h new file +149 -0
149 lines not on this page · raw message
include/linux/f2fs_fs.h +3 -1
@@ -91,7 +91,9 @@ struct f2fs_super_block {__u8 version[VERSION_LEN ];/* the kernel version */ __u8 init_version[VERSION_LEN ];/* the initial kernel version */ __le32 feature;/* defined features */ -__u8 reserved[888 ];/* valid reserved region */ +__u8 encryption_level;/* versioning level for encryption */ +__u8 encrypt_pw_salt[16 ];/* Salt used for string2key algorithm */ +__u8 reserved[871 ];/* valid reserved region */ } __packed;/*
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Re: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 1 line · Jaegeuk Kim
This definitions will be used by inode and superblock for encyption.
How much of this crypto stuff is common with or only slightly modified from the ext4 code? Is the behaviour and features the same? Is the user API and management tools the same?
IMO, if there is any amount of overlap, then we should be implementing this stuff as generic code, not propagating the same code through multiple filesystems via copy-n-paste-n-modify. This will simply end up with diverging code, different bugs and feature sets, and none of the implementations will get the review and maintenance they really require...
And, FWIW, this is the reason why I originally asked for the ext4 encryption code to be pulled up to the VFS: precisely so we didn't end up with a rapid proliferation of individual in-filesystem encryption implementations that are all slightly different...
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Re: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 14 lines · Dave Chinner
Quoted 1 line · Jaegeuk Kim
This definitions will be used by inode and superblock for encyption.
How much of this crypto stuff is common with or only slightly modified from the ext4 code? Is the behaviour and features the same? Is the user API and management tools the same?
IMO, if there is any amount of overlap, then we should be implementing this stuff as generic code, not propagating the same code through multiple filesystems via copy-n-paste-n-modify. This will simply end up with diverging code, different bugs and feature sets, and none of the implementations will get the review and maintenance they really require...
Quoted 9 lines
And, FWIW, this is the reason why I originally asked for the ext4 encryption code to be pulled up to the VFS: precisely so we didn't end up with a rapid proliferation of individual in-filesystem encryption implementations that are all slightly different...
Cheers,
Dave.
Dave,
I have been only reading this discussion for the last few so I may miss a thing or two. Firstly, I have to agree with you on moving the encryption code from the ext4 code base to the VFS layer so other file systems can reuse it. Further more I am curious if you can help me understand why the ext4 developers have decided not to do this as it seems illogical to me. Clearly a reusable core for file system encryption is ideal where the file systems only change it for their internal lay out and design differences much like the way super blocks are handled now in the VFS and by the different file systems that Linux supports. Nick
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerRe: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
In reply to Dave ChinnerQuoted 14 lines · Dave Chinner
Quoted 1 line · Jaegeuk Kim
This definitions will be used by inode and superblock for encyption.
How much of this crypto stuff is common with or only slightly modified from the ext4 code? Is the behaviour and features the same? Is the user API and management tools the same?
IMO, if there is any amount of overlap, then we should be implementing this stuff as generic code, not propagating the same code through multiple filesystems via copy-n-paste-n-modify. This will simply end up with diverging code, different bugs and feature sets, and none of the implementations will get the review and maintenance they really require...
Quoted 4 lines
And, FWIW, this is the reason why I originally asked for the ext4 encryption code to be pulled up to the VFS: precisely so we didn't end up with a rapid proliferation of individual in-filesystem encryption implementations that are all slightly different...
Totally agreed!
AFAIK, Ted wants to push the codes as a crypto library into fs/ finally, so I believe most part of crypto codes are common.
But, in order to realize that quickly, Ted implemented the feature to finalize on-disk and in-memory design in EXT4 as a first step.
Then, I've been catching up and validating its design by implementing it in F2FS, which also intends to figure out what crypto codes can be exactly common.
As Ted mentioned before, since next android version tries to use per-file encryption, F2FS also needs to support it as quick as possible likewise EXT4.
Meanwhile, surely I've been working on writing patches to push them into fs/; currenlty, I did for cryto.c and will do for crypto_key.c and crypto_fname.c. But, it needs to think about crypto_policy.c differently, since it may depend on how each filesystem stores the policy information respectively; we cannot push all the filesystems should use xattrs, right?
Anyway, let me take a time to work on this and submit RFC patches.
Thanks,
Re: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 20 lines · Jaegeuk Kim
Quoted 14 lines · Dave Chinner
Quoted 1 line · Jaegeuk Kim
This definitions will be used by inode and superblock for encyption.
How much of this crypto stuff is common with or only slightly modified from the ext4 code? Is the behaviour and features the same? Is the user API and management tools the same?
IMO, if there is any amount of overlap, then we should be implementing this stuff as generic code, not propagating the same code through multiple filesystems via copy-n-paste-n-modify. This will simply end up with diverging code, different bugs and feature sets, and none of the implementations will get the review and maintenance they really require...
Quoted 4 lines
And, FWIW, this is the reason why I originally asked for the ext4 encryption code to be pulled up to the VFS: precisely so we didn't end up with a rapid proliferation of individual in-filesystem encryption implementations that are all slightly different...
Quoted 4 lines
Totally agreed!
AFAIK, Ted wants to push the codes as a crypto library into
fs/finally, so I believe most part of crypto codes are common.
Can I suggest fs/crypto/ if there are going to be multiple files?
Quoted 4 lines
But, in order to realize that quickly, Ted implemented the feature to finalize on-disk and in-memory design in EXT4 as a first step.
Then, I've been catching up and validating its design by implementing it in F2FS, which also intends to figure out what crypto codes can be exactly common.
Excellent. That will make it easier and less error prone for other filesystems to implement it, too!
Quoted 2 lines
As Ted mentioned before, since next android version tries to use per-file encryption, F2FS also needs to support it as quick as possible likewise EXT4.
Fair enough.
Quoted 5 lines
Meanwhile, surely I've been working on writing patches to push them into
fs/; currenlty, I did forcryto.cand will do forcrypto_key.candcrypto_fname.c. But, it needs to think aboutcrypto_policy.cdifferently, since it may depend on how each filesystem stores the policy information respectively; we cannot push all the filesystems should use xattrs, right?
All filesystems likely to implement per-file crypto support xattrs, and this is exactly what xattrs are designed for. e.g. we already require xattrs for generic security labels, ACLs, etc. Hence per-file crypto information should also use a common, shared xattr format. That way it only needs to be implemented once in the generic code and there's very little (hopefully nothing!) each filesystem has to customise to store the crypto information for each file.
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Jaegeuk Kim
maintainerRe: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 21 lines · Dave Chinner
Quoted 20 lines · Jaegeuk Kim
Quoted 18 lines · Dave Chinner
Quoted 1 line · Jaegeuk Kim
This definitions will be used by inode and superblock for encyption.
How much of this crypto stuff is common with or only slightly modified from the ext4 code? Is the behaviour and features the same? Is the user API and management tools the same?
IMO, if there is any amount of overlap, then we should be implementing this stuff as generic code, not propagating the same code through multiple filesystems via copy-n-paste-n-modify. This will simply end up with diverging code, different bugs and feature sets, and none of the implementations will get the review and maintenance they really require...
And, FWIW, this is the reason why I originally asked for the ext4 encryption code to be pulled up to the VFS: precisely so we didn't end up with a rapid proliferation of individual in-filesystem encryption implementations that are all slightly different...
Quoted 6 lines
Quoted 4 lines
Totally agreed!
AFAIK, Ted wants to push the codes as a crypto library into
fs/finally, so I believe most part of crypto codes are common.Can I suggest
fs/crypto/if there are going to be multiple files?
No problem at all. I'll do.
Quoted 20 lines
Quoted 5 lines
But, in order to realize that quickly, Ted implemented the feature to finalize on-disk and in-memory design in EXT4 as a first step.
Then, I've been catching up and validating its design by implementing it in F2FS, which also intends to figure out what crypto codes can be exactly common.Excellent. That will make it easier and less error prone for other filesystems to implement it, too!
Quoted 2 lines
As Ted mentioned before, since next android version tries to use per-file encryption, F2FS also needs to support it as quick as possible likewise EXT4.
Fair enough.
Quoted 5 lines
Meanwhile, surely I've been working on writing patches to push them into
fs/; currenlty, I did forcryto.cand will do forcrypto_key.candcrypto_fname.c. But, it needs to think aboutcrypto_policy.cdifferently, since it may depend on how each filesystem stores the policy information respectively; we cannot push all the filesystems should use xattrs, right?
Quoted 7 lines
All filesystems likely to implement per-file crypto support xattrs, and this is exactly what xattrs are designed for. e.g. we already require xattrs for generic security labels, ACLs, etc. Hence per-file crypto information should also use a common, shared xattr format. That way it only needs to be implemented once in the generic code and there's very little (hopefully nothing!) each filesystem has to customise to store the crypto information for each file.
Ok, I see. Let me take a look at that too.
Thank you for sharing your thoughts. :)
Quoted 7 lines
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Re: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Please keep in mind that I'm also working on transparent compression. I'm watching this thread closely so that I can implement a compression library alongside the crypto library. If there is any interest or benefit, I would be glad to work together so that the two can be done cooperatively at the same time.
Quoted 63 lines · Jaegeuk Kim
Quoted 19 lines · Dave Chinner
Quoted 18 lines · Jaegeuk Kim
Quoted 17 lines · Dave Chinner
Quoted 1 line · Jaegeuk Kim
This definitions will be used by inode and superblock for encyption.
How much of this crypto stuff is common with or only slightly modified from the ext4 code? Is the behaviour and features the same? Is the user API and management tools the same?
IMO, if there is any amount of overlap, then we should be implementing this stuff as generic code, not propagating the same code through multiple filesystems via copy-n-paste-n-modify. This will simply end up with diverging code, different bugs and feature sets, and none of the implementations will get the review and maintenance they really require...
And, FWIW, this is the reason why I originally asked for the ext4 encryption code to be pulled up to the VFS: precisely so we didn't end up with a rapid proliferation of individual in-filesystem encryption implementations that are all slightly different...
Quoted 5 lines
Quoted 4 lines
Totally agreed!
AFAIK, Ted wants to push the codes as a crypto library into
fs/finally, so I believe most part of crypto codes are common.Can I suggest
fs/crypto/if there are going to be multiple files?No problem at all. I'll do.
Quoted 16 lines
Quoted 4 lines
But, in order to realize that quickly, Ted implemented the feature to finalize on-disk and in-memory design in EXT4 as a first step.
Then, I've been catching up and validating its design by implementing it in F2FS, which also intends to figure out what crypto codes can be exactly common.Excellent. That will make it easier and less error prone for other filesystems to implement it, too!
Quoted 2 lines
As Ted mentioned before, since next android version tries to use per-file encryption, F2FS also needs to support it as quick as possible likewise EXT4.
Fair enough.
Quoted 5 lines
Meanwhile, surely I've been working on writing patches to push them into
fs/; currenlty, I did forcryto.cand will do forcrypto_key.candcrypto_fname.c. But, it needs to think aboutcrypto_policy.cdifferently, since it may depend on how each filesystem stores the policy information respectively; we cannot push all the filesystems should use xattrs, right?Quoted 7 lines
All filesystems likely to implement per-file crypto support xattrs, and this is exactly what xattrs are designed for. e.g. we already require xattrs for generic security labels, ACLs, etc. Hence per-file crypto information should also use a common, shared xattr format. That way it only needs to be implemented once in the generic code and there's very little (hopefully nothing!) each filesystem has to customise to store the crypto information for each file.
Ok, I see. Let me take a look at that too.
Thank you for sharing your thoughts. :)Quoted 6 lines
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Jaegeuk Kim
maintainerRe: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 5 lines · Tom Marshall
Please keep in mind that I'm also working on transparent compression. I'm watching this thread closely so that I can implement a compression library alongside the crypto library. If there is any interest or benefit, I would be glad to work together so that the two can be done cooperatively at the same time.
I can't imagine quickly how compression code can be shared with crypto. The basic approach for compression would be that X pages can be compressed into small number of pages, Y, which can be a X to Y mapping.
But, this per-file encryption supports only 1 to 1 4KB mapping, so that it could be quite a simple implementation.
Could you elaborate on your approach or design? Or, codes? Whatever, IMO, it needs to implement it by any filesystem first.
Thanks,
Quoted 65 lines · Jaegeuk Kim
Quoted 63 lines · Dave Chinner
Quoted 19 lines · Jaegeuk Kim
Quoted 18 lines · Dave Chinner
Quoted 17 lines · Jaegeuk Kim
Quoted 1 line
This definitions will be used by inode and superblock for encyption.
How much of this crypto stuff is common with or only slightly modified from the ext4 code? Is the behaviour and features the same? Is the user API and management tools the same?
IMO, if there is any amount of overlap, then we should be implementing this stuff as generic code, not propagating the same code through multiple filesystems via copy-n-paste-n-modify. This will simply end up with diverging code, different bugs and feature sets, and none of the implementations will get the review and maintenance they really require...
And, FWIW, this is the reason why I originally asked for the ext4 encryption code to be pulled up to the VFS: precisely so we didn't end up with a rapid proliferation of individual in-filesystem encryption implementations that are all slightly different...
Quoted 5 lines
Quoted 4 lines
Totally agreed!
AFAIK, Ted wants to push the codes as a crypto library into
fs/finally, so I believe most part of crypto codes are common.Can I suggest
fs/crypto/if there are going to be multiple files?No problem at all. I'll do.
Quoted 16 lines
Quoted 4 lines
But, in order to realize that quickly, Ted implemented the feature to finalize on-disk and in-memory design in EXT4 as a first step.
Then, I've been catching up and validating its design by implementing it in F2FS, which also intends to figure out what crypto codes can be exactly common.Excellent. That will make it easier and less error prone for other filesystems to implement it, too!
Quoted 2 lines
As Ted mentioned before, since next android version tries to use per-file encryption, F2FS also needs to support it as quick as possible likewise EXT4.
Fair enough.
Quoted 5 lines
Meanwhile, surely I've been working on writing patches to push them into
fs/; currenlty, I did forcryto.cand will do forcrypto_key.candcrypto_fname.c. But, it needs to think aboutcrypto_policy.cdifferently, since it may depend on how each filesystem stores the policy information respectively; we cannot push all the filesystems should use xattrs, right?Quoted 7 lines
All filesystems likely to implement per-file crypto support xattrs, and this is exactly what xattrs are designed for. e.g. we already require xattrs for generic security labels, ACLs, etc. Hence per-file crypto information should also use a common, shared xattr format. That way it only needs to be implemented once in the generic code and there's very little (hopefully nothing!) each filesystem has to customise to store the crypto information for each file.
Ok, I see. Let me take a look at that too.
Thank you for sharing your thoughts. :)Quoted 6 lines
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 7 lines · Jaegeuk Kim
Quoted 5 lines · Tom Marshall
Please keep in mind that I'm also working on transparent compression. I'm watching this thread closely so that I can implement a compression library alongside the crypto library. If there is any interest or benefit, I would be glad to work together so that the two can be done cooperatively at the same time.
Quoted 5 lines
I can't imagine quickly how compression code can be shared with crypto. The basic approach for compression would be that X pages can be compressed into small number of pages, Y, which can be a X to Y mapping.
But, this per-file encryption supports only 1 to 1 4KB mapping, so that it could be quite a simple implementation.
No, I don't intend to share actual code with crypto -- at least not much. I'm more interested in looking at how the crypto layer is implemented to give me clues about how to implement a compression layer.
Quoted 2 lines
Could you elaborate on your approach or design? Or, codes? Whatever, IMO, it needs to implement it by any filesystem first.
I don't really have any working code yet. I will probably get to that in the coming few weeks. Right now I'm still working with the ugly VFS stacking implementation that I posted initially.
The thing that I have done is dismissed the standard compression framing formats.
zlib (and gzip) are designed for streaming and it is quite difficult to implement random access on it. See the example code in the zlib source, zran.c. It's not really tenable because 32kb of prior data is required to be kept as priming information. Even doing fully encapsulated blocks with Z_FINISH, there is still no way to skip over data without decompressing it first to build an index.
lz4 is somewhat better in that blocks are self contained. But block lengths must be read sequentially. This means that reading an arbitrary position in a file requires a proportional number of reads to find the desired block.
So, I am working with a simple framing format that I threw together. The header has a compression method (zlib or lz4), block size, original input size, and a block map.
Jaegeuk Kim
maintainerRe: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 14 lines · Tom Marshall
Quoted 7 lines · Jaegeuk Kim
Quoted 5 lines · Tom Marshall
Please keep in mind that I'm also working on transparent compression. I'm watching this thread closely so that I can implement a compression library alongside the crypto library. If there is any interest or benefit, I would be glad to work together so that the two can be done cooperatively at the same time.
Quoted 5 lines
I can't imagine quickly how compression code can be shared with crypto. The basic approach for compression would be that X pages can be compressed into small number of pages, Y, which can be a X to Y mapping.
But, this per-file encryption supports only 1 to 1 4KB mapping, so that it could be quite a simple implementation.
Quoted 3 lines
No, I don't intend to share actual code with crypto -- at least not much. I'm more interested in looking at how the crypto layer is implemented to give me clues about how to implement a compression layer.
Ok, I see.
Currently, I've been writing up fs/crypto having shared crypto codes between ext4 and f2fs; I refactored existing codes a little bit though.
I'm approaching to introduce a fscypt_operations for each filesystems like this.
struct fscrypt_operations {
int (*get_context)(struct inode *, void *, size_t, void *);
int (*set_context)(struct inode *, const void *, size_t, int, void *);
int (*prepare_new_context)(struct inode *);
bool (*is_encrypted)(struct inode *);
bool (*empty_dir)(struct inode *);
unsigned (*max_namelen)(struct inode *);
};And, the following two basic functions will be used by filesystems:fscrypt_encrypt_page() and fscrypt_decrypt_page().
Quoted 18 lines
Quoted 3 lines
Could you elaborate on your approach or design? Or, codes? Whatever, IMO, it needs to implement it by any filesystem first.
I don't really have any working code yet. I will probably get to that in the coming few weeks. Right now I'm still working with the ugly VFS stacking implementation that I posted initially.
The thing that I have done is dismissed the standard compression framing formats.
zlib (and gzip) are designed for streaming and it is quite difficult to implement random access on it. See the example code in the zlib source,
zran.c. It's not really tenable because 32kb of prior data is required to be kept as priming information. Even doing fully encapsulated blocks withZ_FINISH, there is still no way to skip over data without decompressing it first to build an index.
Quoted 7 lines
lz4 is somewhat better in that blocks are self contained. But block lengths must be read sequentially. This means that reading an arbitrary position in a file requires a proportional number of reads to find the desired block.
So, I am working with a simple framing format that I threw together. The header has a compression method (zlib or lz4), block size, original input size, and a block map.
Thank you for sharing the approach, and it makes sense to improve random read performance.
Thanks,
Re: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
In reply to Dave ChinnerQuoted 5 lines · Dave Chinner
Quoted 3 lines
AFAIK, Ted wants to push the codes as a crypto library into
fs/finally, so I believe most part of crypto codes are common.Can I suggest
fs/crypto/if there are going to be multiple files?
Yes, I think we definitely want to do this as fs/crypto; it makes things a bit more straightforward on a number of fronts; not just from a Makefile point of view, but also in setting up a separate tree to push into linux-next.
Quoted 7 lines
Quoted 4 lines
But, in order to realize that quickly, Ted implemented the feature to finalize on-disk and in-memory design in EXT4 as a first step.
Then, I've been catching up and validating its design by implementing it in F2FS, which also intends to figure out what crypto codes can be exactly common.Excellent. That will make it easier and less error prone for other filesystems to implement it, too!
Yeah, that's why I figured it would be easier to get it into ext4 and f2fs first. We can keep the functions in sync for a release or so, and then we can start creating patches that gradually move each of fs/{ext4,f2fs}/{crypto,crypo_fname,crypto_policy}.c, etc. into a common fs/crypto directory. I'm sure there will be a bit of refactoring that will be necessary as we go along, but it will be a lot easier to validate that we've gotten things once we have to file systems both depending on the common code.
If Michael and I had tried to create fs/cryto up-front, I'm *sure* we would have gotten a number of things wrong. :-)
Quoted 6 lines
Quoted 5 lines
Meanwhile, surely I've been working on writing patches to push them into
fs/; currenlty, I did forcryto.cand will do forcrypto_key.candcrypto_fname.c. But, it needs to think aboutcrypto_policy.cdifferently, since it may depend on how each filesystem stores the policy information respectively; we cannot push all the filesystems should use xattrs, right?
Quoted 7 lines
All filesystems likely to implement per-file crypto support xattrs, and this is exactly what xattrs are designed for. e.g. we already require xattrs for generic security labels, ACLs, etc. Hence per-file crypto information should also use a common, shared xattr format. That way it only needs to be implemented once in the generic code and there's very little (hopefully nothing!) each filesystem has to customise to store the crypto information for each file.
Yes, absolutely. What's going to be more difficult in the long run is when we want to support per-block data integrity, using (for example) AES/GCM, which will require 32 bytes of per-block "authentication tag" (think Message Authentication Code) that have to be committed atomically with the data block write.
Quite frankly, this is going to be much easier for COW file systems like f2fs and btrfs. I have some ideas about how to do this for update-in-place file systems (using either a compression hack and/or storing two generations worth of authentication tag per block), but it's not pretty. (Or in the case of ext4 we could use data=journalling mode, but that's even less pretty from a performance standpoint.)
Cheers,
- Ted
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Re: [PATCH 03/18] f2fs crypto: declare some definitions for f2fs encryption feature
Quoted 6 lines · Theodore Ts'o
[...] What's going to be more difficult in the long run is when we want to support per-block data integrity, using (for example) AES/GCM, which will require 32 bytes of per-block "authentication tag" (think Message Authentication Code) that have to be committed atomically with the data block write.
Quoted 7 lines
Quite frankly, this is going to be much easier for COW file systems like f2fs and btrfs. I have some ideas about how to do this for update-in-place file systems (using either a compression hack and/or storing two generations worth of authentication tag per block), but it's not pretty. (Or in the case of ext4 we could use data=journalling mode, but that's even less pretty from a performance standpoint.)
It seems to me that compression has a similar issue with framing metadata. The block map can be stored upfront, which then would require two writes to update a data block. Or it can be stored inline, which then would require scanning through the file sequentially for random access.
The big difference, of course, is that in the case of compression, we have the luxury of assuming or mandating read-only/read-mostly.
Re: fs compression
So I've been playing around a bit and I have a basic strategy laid out. Please let me know if I'm on the right track.
Compressed file attributes
==========================
The filesystem is responsible for detecting whether a file is compressed and hooking into the compression lib. This may be done with an inode flag, xattr, or any other applicable method. No other special attributes are necessary.
Compressed file format
======================
Compressed files shall have header, block map, and data sections.
Header:
byte[4] magic 'zzzz' (not strictly needed)
byte param1 method and flags
bits 0..3 = compression method (1=zlib, 2=lz4, etc.) bits 4..7 = flags (none defined yet)
byte blocksize log2 of blocksize (max 31)
le48 orig_size original uncompressed file size
Block map:
Vector of le16 (if blocksize <= 16) or le32 (if blocksize > 16). Each entry is the compressed size of the block. Zero indicates that the block is stored uncompressed, in case compression expanded the block.
Data:
Compressed data.
Compression library
===================
I'm just fleshing this out and trying to make it work. The basic strategy is to wrap the underlying readpage/readpages. Right now I have the following:
/*
* For convenience.
*/
typedef int (*readpage_t)(struct page *);
/*
* Indicate whether compression is enabled. It may be desirable to disable
* compression for test, backup, or maintenance activities. Controlled by
* a sysfs file.
*/
extern int zfile_enabled(void);
/*
* Initialize internal data structures for a given inode. This will
* result in reading the file header and block map, so the inode must
* be fully populated and ready to accept readpage requests. */
extern int zinode_init(struct inode *inode, readpage_t lower_readpage);
/*
* Wrapper for filesystem's readpage. Consults the block map and reads
* the appropriate compressed pages for the requested block, decompresses
* them, and populates the page with uncompressed data.
*/
extern int zinode_readpage(readpage_t lower_readpage,
struct page *page);
/*
* As above, but for multiple pages.
*/
extern int zinode_readpages(readpage_t lower_readpage,
struct address_space *mapping, struct list_head *pages, unsigned nr_pages);
Questions and issues
====================
Should there be any padding for the data blocks? For example, if writing is to be supported, padding the compressed data to the filesystem block size would allow for easy rewriting of individual blocks without disturbing the surrounding blocks. Perhaps padding could be indicated by a flag.
Note readpage_t does not take a file ptr, as it's not available at inode creation time. ext4 only uses it to lookup the inode ptr. Is this true across all filesystems, or do some actually require the file ptr in their readpage?
The compression code must be able to read pages from the underlying filesystem. This involves using the pagecache. But the uncompressed data is what ultimately should end up in the pagecache. This is where I'm currently stuck. How do I implement the code such that the underlying compressed data may be read (using the pagecache or not) while not disturbing the pagecache for the uncompressed data? I'm wondering if I need to create an internal address_space to pass down into the underlying readpage? Or is there another way to do this?
Re: fs compression
Quoted 8 lines
The compression code must be able to read pages from the underlying filesystem. This involves using the pagecache. But the uncompressed data is what ultimately should end up in the pagecache. This is where I'm currently stuck. How do I implement the code such that the underlying compressed data may be read (using the pagecache or not) while not disturbing the pagecache for the uncompressed data? I'm wondering if I need to create an internal
address_spaceto pass down into the underlying readpage? Or is there another way to do this?
I created a private address_space for the inode that is passed into the lower readpage. That seems to be working. Is this a cool thing to do (hopefully)?
Re: fs compression
In reply to Tom MarshallQuoted 10 lines · Tom Marshall
So I've been playing around a bit and I have a basic strategy laid out. Please let me know if I'm on the right track.
Compressed file attributes
==========================The filesystem is responsible for detecting whether a file is compressed and hooking into the compression lib. This may be done with an inode flag, xattr, or any other applicable method. No other special attributes are necessary.
So I assume what you are implementing is read-only compression; that is, once the file is written, and the attribute set indicating that this is a compressed file, it is now immutable.
Quoted 5 lines
Compressed file format
======================Compressed files shall have header, block map, and data sections.
Quoted 7 lines
Header:
byte[4] magic 'zzzz' (not strictly needed)
byte param1 method and flagsbits 0..3 = compression method (1=zlib, 2=lz4, etc.) bits 4..7 = flags (none defined yet)byte blocksize log2 of blocksize (max 31)
I suggest using the term "compression cluster" to distinguish this from the file system block size.
Quoted 8 lines
le48
orig_sizeoriginal uncompressed file sizeBlock map:
Vector of le16 (if blocksize <= 16) or le32 (if blocksize > 16). Each entry is the compressed size of the block. Zero indicates that the block is stored uncompressed, in case compression expanded the block.
What I would store instead is list of 32 or 64-bit offsets, where the nth entry in the array indicates the starting offset of the nth compression cluster.
Quoted 1 line
Questions and issues
====================
Quoted 5 lines
Should there be any padding for the data blocks? For example, if writing is to be supported, padding the compressed data to the filesystem block size would allow for easy rewriting of individual blocks without disturbing the surrounding blocks. Perhaps padding could be indicated by a flag.
If you add padding then you defeat the whole point of adding compression. What if the initial contents of a 64k cluster was all zeros, so it trivially compresses down to a few dozen bytes; but then it gets replaced by completely uncompressible data? If you add 64k worth of padding to each block, then you're not saving any space, so what's the point?
Quoted 8 lines
The compression code must be able to read pages from the underlying filesystem. This involves using the pagecache. But the uncompressed data is what ultimately should end up in the pagecache. This is where I'm currently stuck. How do I implement the code such that the underlying compressed data may be read (using the pagecache or not) while not disturbing the pagecache for the uncompressed data? I'm wondering if I need to create an internal
address_spaceto pass down into the underlying readpage? Or is there another way to do this?
So I would *not* reference the compressed data via the page cache. If you do that, then you end up wasting space in the page cache, since the page cache will contain both the compressed and decompressed data --- and once the data has been decompressed, the compressed version is completely useless. So it's better to have the file system supply the physical location on disk, and then to read in the compressed data to a scratched set of page which is freed immediately after you are done decompressing things.
This is why compression is so very different from encryption. The constraints make it quite different.
Regards,
- Ted
Re: fs compression
So I have this all working as described. I haven't implemented readahead yet (readpages) so it's slow. I'll be doing that next.
The other thing to note is that since the uncompressed size is stored inside the file data, stat() requires reading both the inode and the first page of the file. That's not optimal, but I don't know if other generic out-of-band solutions (such as xattrs) would be any better. I suppose it depends on whether the xattr info is read in with the inode or not.
Also, on the subject of file size, I'm currently swapping out the i_size for the compressed i_size before calling down into the filesystem's readpage. Yes that's a nasty hack that I'll need to address.
Quoted 7 lines · Theodore Ts'o
Quoted 6 lines · Tom Marshall
So I've been playing around a bit and I have a basic strategy laid out. Please let me know if I'm on the right track.
Compressed file attributes
==========================
Quoted 8 lines
Quoted 4 lines
The filesystem is responsible for detecting whether a file is compressed and hooking into the compression lib. This may be done with an inode flag, xattr, or any other applicable method. No other special attributes are necessary.
So I assume what you are implementing is read-only compression; that is, once the file is written, and the attribute set indicating that this is a compressed file, it is now immutable.
That is TBD. Our use case right now only requires read-only, but I think read-write would be a nice thing if it's not too convoluted.
fallocate() is supported on the major filesystems, and I imagine the same mechanisms could be used to provide rewriting of the "compression clusters".
Quoted 7 lines
Quoted 7 lines
Compressed file format
======================Compressed files shall have header, block map, and data sections.
Header:
Quoted 8 lines
Quoted 5 lines
byte[4] magic 'zzzz' (not strictly needed)
byte param1 method and flagsbits 0..3 = compression method (1=zlib, 2=lz4, etc.) bits 4..7 = flags (none defined yet)byte blocksize log2 of blocksize (max 31)
I suggest using the term "compression cluster" to distinguish this from the file system block size.
Sure, just a name...
Quoted 5 lines
Quoted 5 lines
le48
orig_sizeoriginal uncompressed file sizeBlock map:
Quoted 7 lines
Quoted 3 lines
Vector of le16 (if blocksize <= 16) or le32 (if blocksize > 16). Each entry is the compressed size of the block. Zero indicates that the block is stored uncompressed, in case compression expanded the block.
What I would store instead is list of 32 or 64-bit offsets, where the nth entry in the array indicates the starting offset of the nth compression cluster.
Why? This would both increase the space requirements and require some other mechanism to indicate uncompressed compression clusters (eg. setting the high bit or something).
Quoted 8 lines
Quoted 1 line
Questions and issues
====================
Quoted 5 lines
Should there be any padding for the data blocks? For example, if writing is to be supported, padding the compressed data to the filesystem block size would allow for easy rewriting of individual blocks without disturbing the surrounding blocks. Perhaps padding could be indicated by a flag.
Quoted 6 lines
If you add padding then you defeat the whole point of adding compression. What if the initial contents of a 64k cluster was all zeros, so it trivially compresses down to a few dozen bytes; but then it gets replaced by completely uncompressible data? If you add 64k worth of padding to each block, then you're not saving any space, so what's the point?
Sorry, I meant padding to the filesystem block size. So, for example, if a 64kb compression cluster is compressed to 31kb, it would use 8*4kb blocks and the next compression cluster would start on a new block.
Quoted 9 lines
Quoted 8 lines
The compression code must be able to read pages from the underlying filesystem. This involves using the pagecache. But the uncompressed data is what ultimately should end up in the pagecache. This is where I'm currently stuck. How do I implement the code such that the underlying compressed data may be read (using the pagecache or not) while not disturbing the pagecache for the uncompressed data? I'm wondering if I need to create an internal
address_spaceto pass down into the underlying readpage? Or is there another way to do this?
Quoted 8 lines
So I would *not* reference the compressed data via the page cache. If you do that, then you end up wasting space in the page cache, since the page cache will contain both the compressed and decompressed data --- and once the data has been decompressed, the compressed version is completely useless. So it's better to have the file system supply the physical location on disk, and then to read in the compressed data to a scratched set of page which is freed immediately after you are done decompressing things.
I'm currently using an internal address_space to pass down into the underlying filesystem to make things easy. I'm too inexperienced in filesystem development to unravel how to plumb in anything else (but I'm learning quickly!)
If you have ideas about how to do the underlying readpage without the pagecache, please enlighten me.
Or perhaps I could manually release the page from the private cache after the uncompressed data has been extracted?
Quoted 9 lines
This is why compression is so very different from encryption. The constraints make it quite different.
Regards,
- Ted
Re: fs compression
Quoted 30 lines · Tom Marshall
So I have this all working as described. I haven't implemented readahead yet (readpages) so it's slow. I'll be doing that next.
The other thing to note is that since the uncompressed size is stored inside the file data,
stat()requires reading both the inode and the first page of the file. That's not optimal, but I don't know if other generic out-of-band solutions (such as xattrs) would be any better. I suppose it depends on whether the xattr info is read in with the inode or not.Also, on the subject of file size, I'm currently swapping out the
i_sizefor the compressedi_sizebefore calling down into the filesystem's readpage. Yes that's a nasty hack that I'll need to address.Quoted 7 lines · Theodore Ts'o
Quoted 6 lines · Tom Marshall
So I've been playing around a bit and I have a basic strategy laid out. Please let me know if I'm on the right track.
Compressed file attributes
==========================Quoted 8 lines
Quoted 4 lines
The filesystem is responsible for detecting whether a file is compressed and hooking into the compression lib. This may be done with an inode flag, xattr, or any other applicable method. No other special attributes are necessary.
So I assume what you are implementing is read-only compression; that is, once the file is written, and the attribute set indicating that this is a compressed file, it is now immutable.
Quoted 5 lines
That is TBD. Our use case right now only requires read-only, but I think read-write would be a nice thing if it's not too convoluted.
fallocate()is supported on the major filesystems, and I imagine the same mechanisms could be used to provide rewriting of the "compression clusters".
It just occurred to me that this could be the answer to both a consistent i_size and providing read-write access.
If compression clusters were implemented by holes in the underlying file and the header+blockmap were not stored in the file proper, then the compressed and uncompressed file sizes would match.
Further, rewriting a compression cluster would be a simple matter of adjusting the allocated compression cluster blocks as fallocate() provides.
I honestly don't have a clue how to storing the header+blockmap outside the file yet, but if we could, that would seem to tie everything together quite nicely.
Thoughts?
Re: fs compression
As I mentioned earlier, I had a hack working for transparent file compression. But it has a few problems. The two major ones are (1) It reads the lower pages synchronously by waiting on pages with wait_on_page_locked(), destroying readahead, and (2) it is swapping out i_size to call the lower readpage. So I'm ditching that and going another route.
My idea now is to create a wrapper inode that is passed back to the VFS layer. The wrapper inode would have the correct i_size, blkbits, and implement address_space_operations. The implementation of readpage/readpages would then call down into the lower filesystem's readpage/readpages to fetch compressed data. When the required pages are available, it would decompress and populate its own requested pages.
But one thing I'm wrestling with is how to be asynchronously notified when the lower readpage/readpages complete. The two ideas that come to mind are (1) plumbing a callback into mpage_end_io(), (2) allowing override of mpage_end_io() with a custom function, (3) creating kernel threads analogous to kblockd to wait for pending pages.
But again, I'm new at this, so maybe there's an easier or better way?
Re: fs compression
Quoted 5 lines · Tom Marshall
But one thing I'm wrestling with is how to be asynchronously notified when the lower readpage/readpages complete. The two ideas that come to mind are
(1) plumbing a callback intompage_end_io(), (2) allowing override ofmpage_end_io()with a custom function, (3) creating kernel threads analogous to kblockd to wait for pending pages.
Not all file systems use mpage_end_io(), so that's not a good solution.
You can do something like
wait_on_page_bit(page, PG_uptodate);
... although to be robust you will also need to wake up if PG_error is set (if there is an I/O error, PG_error is set instead of PG_uptodate). So that means you'd have to spin your own wait function using the waitqueue primitives and page_waitqueue(), using __wait_on_bit() as an initial model.
This suggestion should not be taken as an endorsement of your higher-levle architecture. I suggest you think very carefully about whether or not you need to be able to support random write functionality, and if you don't, there are simpler ways such as the one I outlined to you earlier.
Regards, and good luck,
- Ted
Re: fs compression
Quoted 9 lines · Theodore Ts'o
Quoted 5 lines · Tom Marshall
But one thing I'm wrestling with is how to be asynchronously notified when the lower readpage/readpages complete. The two ideas that come to mind are
(1) plumbing a callback intompage_end_io(), (2) allowing override ofmpage_end_io()with a custom function, (3) creating kernel threads analogous to kblockd to wait for pending pages.Not all file systems use
mpage_end_io(), so that's not a good solution.
Ah, thanks, I was not aware of that. So that leaves waiting on pages, which probably means a fair amount of plumbing to do correctly.
Quoted 9 lines
You can do something like
wait_on_page_bit(page, PG_uptodate);... although to be robust you will also need to wake up if
PG_erroris set (if there is an I/O error,PG_erroris set instead ofPG_uptodate). So that means you'd have to spin your own wait function using the waitqueue primitives andpage_waitqueue(), using__wait_on_bit()as an initial model.
Right, that should be pretty easy.
Quoted 5 lines
This suggestion should not be taken as an endorsement of your higher-levle architecture. I suggest you think very carefully about whether or not you need to be able to support random write functionality, and if you don't, there are simpler ways such as the one I outlined to you earlier.
I recall this:
Quoted 3 lines
[...] So it's better to have the file system supply the physical location on disk, and then to read in the compressed data to a scratched set of page which is freed immediately after you are done decompressing things.
Is that what you're referring to?
If so, I'm not seeing how this makes things simpler. It's still asynchronous, right? ext4_readpage calls back into mpage_readpage which uses ext4_get_block, which then queues a bio request. I don't see any way to avoid queueing asynchronous bio requests or even getting completion notifications.
Now, I could pass ext4_get_block up into my code and setup my own bio requests so that I can get callbacks. But this basically means implementing the equivalent of do_mpage_readpage in my own code, and that's not really trivial code to copy/paste/hack. And it also doesn't address filesystems that don't use mpage_end_io(), right?
Am I missing something?
Re: fs compression
In reply to Theodore Ts'oQuoted 12 lines · Theodore Ts'o
Quoted 5 lines · Tom Marshall
But one thing I'm wrestling with is how to be asynchronously notified when the lower readpage/readpages complete. The two ideas that come to mind are
(1) plumbing a callback intompage_end_io(), (2) allowing override ofmpage_end_io()with a custom function, (3) creating kernel threads analogous to kblockd to wait for pending pages.Not all file systems use
mpage_end_io(), so that's not a good solution.You can do something like
Quoted 7 lines
wait_on_page_bit(page, PG_uptodate);... although to be robust you will also need to wake up if
PG_erroris set (if there is an I/O error,PG_erroris set instead ofPG_uptodate). So that means you'd have to spin your own wait function using the waitqueue primitives andpage_waitqueue(), using__wait_on_bit()as an initial model.
My current thought is to use a workqueue and queue a work object for each cluster read that is in flight. The work function does wait_on_page_locked for each lower page. If/when all complete without error, the data is then decompressed and the upper pages are entered. This is currently a work in progress, it's not yet functional.
So basically my questions here are:
(1) Does this seem sane?
(2) Is it ok to wait on !locked instead of waiting on (uptodate|error)?
(3) Do I need to mark a pending cluster pending to prevent simultaneous reads of the same cluster (especially since the cluster size will be much larger than the lower block size)?
Also note I've now realized that the logical conclusion to the wrapper inode idea is a stacked filesystem. That's not the direction we are aiming for, so instead I'm adding a "struct xcomp_inode_info" to ext4_inode_info, which can then be passed back into the xcomp functions.
Re: fs compression
So I've just gotten this all working. The last notable change I made was to inode size: I added an i_compressed_size member and then did some macro hackage to ensure that the fs implementation (eg. fs/ext4) sees the compressed size while everything else sees the uncompressed size.
I'll be testing further tomorrow.
Quoted 41 lines · Tom Marshall
Quoted 12 lines · Theodore Ts'o
Quoted 5 lines · Tom Marshall
But one thing I'm wrestling with is how to be asynchronously notified when the lower readpage/readpages complete. The two ideas that come to mind are
(1) plumbing a callback intompage_end_io(), (2) allowing override ofmpage_end_io()with a custom function, (3) creating kernel threads analogous to kblockd to wait for pending pages.Not all file systems use
mpage_end_io(), so that's not a good solution.You can do something like
Quoted 7 lines
wait_on_page_bit(page, PG_uptodate);... although to be robust you will also need to wake up if
PG_erroris set (if there is an I/O error,PG_erroris set instead ofPG_uptodate). So that means you'd have to spin your own wait function using the waitqueue primitives andpage_waitqueue(), using__wait_on_bit()as an initial model.My current thought is to use a workqueue and queue a work object for each cluster read that is in flight. The work function does
wait_on_page_lockedfor each lower page. If/when all complete without error, the data is then decompressed and the upper pages are entered. This is currently a work in progress, it's not yet functional.So basically my questions here are:
(1) Does this seem sane?
(2) Is it ok to wait on !locked instead of waiting on (uptodate|error)?
(3) Do I need to mark a pending cluster pending to prevent simultaneous reads of the same cluster (especially since the cluster size will be much larger than the lower block size)?
Also note I've now realized that the logical conclusion to the wrapper inode idea is a stacked filesystem. That's not the direction we are aiming for, so instead I'm adding a "struct
xcomp_inode_info" toext4_inode_info, which can then be passed back into the xcomp functions.
Re: fs compression
Quoted 6 lines · Tom Marshall
So I've just gotten this all working. The last notable change I made was to inode size: I added an
i_compressed_sizemember and then did some macro hackage to ensure that the fs implementation (eg. fs/ext4) sees the compressed size while everything else sees the uncompressed size.I'll be testing further tomorrow.
I seem to have a race condition that leads to deadlock. Though I was able to boot to home screen on a device after a couple tries. Investigating.
Here's my diff to include/linux/fs.h for the inode stuff based on 3.10. It requires/assumes that filesystems implementing transparent compression will define FS_IMPL in their Makefile. It's not final, just the first thing that worked. Any suggestions on how the final version should look .. or alternate ideas for how to do this?
include/linux/fs.h +11 -2
@@ -554,6 +554,9 @@ struct inode { };dev_t i_rdev;loff_t i_size; +#ifdef CONFIG_FS_TRANSPARENT_COMPRESSION +loff_t i_compressed_size; +#endif struct timespec i_atime;struct timespec i_mtime;struct timespec i_ctime;
@@ -635,6 +638,12 @@ enum inode_i_mutex_lock_class I_MUTEX_QUOTA }; +#if defined(CONFIG_FS_TRANSPARENT_COMPRESSION ) && defined(FS_IMPL ) +#define I_SIZE_MEMBER i_compressed_size +#else +#define I_SIZE_MEMBER i_size +#endif +/* * NOTE: in a 32bit arch with a preemptable kernel and * an UP compile the i_size_read/write must be atomic
@@ -653,14 +662,14 @@ static inline loff_t i_size_read(const struct inode *inode)do { seq =read_seqcount_begin (&inode->i_size_seqcount); - i_size = inode->i_size; + i_size = inode->I_SIZE_MEMBER; }while (read_seqcount_retry (&inode->i_size_seqcount, seq));return i_size;#elif BITS_PER_LONG ==32 && defined(CONFIG_PREEMPT )loff_t i_size;preempt_disable (); - i_size = inode->i_size; + i_size = inode->I_SIZE_MEMBER;preempt_enable ();return i_size;#else
Re: fs compression
I think transparent compression is fully functional now. I'm sending a short patch series for comments.
Jaegeuk Kim
maintainerPATCH 4/18 f2fs crypto: add f2fs encryption Kconfig
In reply to Jaegeuk KimThis patch adds f2fs encryption config.
--- fs/f2fs/Kconfig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
fs/f2fs/Kconfig +18 -0
@@ -72,6 +72,24 @@ config F2FS_CHECK_FS If you want to improve the performance, say N. +config F2FS_FS_ENCRYPTION + bool "F2FS Encryption" + depends on F2FS_FS + depends on F2FS_FS_XATTR + select CRYPTO_AES + select CRYPTO_CBC + select CRYPTO_ECB + select CRYPTO_XTS + select CRYPTO_CTS + select CRYPTO_SHA256 + select KEYS + select ENCRYPTED_KEYS + help + Enable encryption of f2fs files and directories. This + feature is similar to ecryptfs, but it is more memory + efficient since it avoids caching the encrypted and + decrypted pages in the page cache. + config F2FS_IO_TRACE bool "F2FS IO tracer" depends on F2FS_FS
Signature · 1 line
2.1.1
Jaegeuk Kim
maintainerPATCH 5/18 f2fs crypto: add encryption xattr support
In reply to Jaegeuk KimThis patch add some definition for enrcyption xattr.
--- fs/f2fs/xattr.h | 4 ++++ 1 file changed, 4 insertions(+)
fs/f2fs/xattr.h +4 -0
@@ -35,6 +35,10 @@#define F2FS_XATTR_INDEX_LUSTRE 5#define F2FS_XATTR_INDEX_SECURITY 6#define F2FS_XATTR_INDEX_ADVISE 7 +/* Should be same as EXT4_XATTR_INDEX_ENCRYPTION */ +#define F2FS_XATTR_INDEX_ENCRYPTION 9 + +#define F2FS_XATTR_NAME_ENCRYPTION_CONTEXT "c"struct f2fs_xattr_header {__le32 h_magic;/* magic number for identification */
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 6/18 f2fs crypto: add encryption policy and password salt support
In reply to Jaegeuk KimThis patch adds encryption policy and password salt support through ioctl implementation.
It adds three ioctls:
F2FS_IOC_SET_ENCRYPTION_POLICY, F2FS_IOC_GET_ENCRYPTION_POLICY, F2FS_IOC_GET_ENCRYPTION_PWSALT, which use xattr operations.
Note that, these definition and codes are taken from ext4 crypto support. For f2fs, xattr operations and on-disk flags for superblock and inode were changed.
--- fs/f2fs/Makefile | 1 + fs/f2fs/crypto_policy.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/f2fs/f2fs.h | 16 ++++ fs/f2fs/file.c | 91 +++++++++++++++++++++ fs/f2fs/xattr.c | 3 + 5 files changed, 317 insertions(+) create mode 100644 fs/f2fs/crypto_policy.c
fs/f2fs/Makefile +1 -0
@@ -6,3 +6,4 @@ f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o f2fs-$(CONFIG_F2FS_IO_TRACE) += trace.o +f2fs-$(CONFIG_F2FS_FS_ENCRYPTION) += crypto_policy.o
fs/f2fs/crypto_policy.c new file +206 -0
206 lines not on this page · raw message
fs/f2fs/f2fs.h +16 -0
@@ -229,6 +229,13 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,#define F2FS_IOC_RELEASE_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 4)#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) +#define F2FS_IOC_SET_ENCRYPTION_POLICY \ + _IOR('f', 19, struct f2fs_encryption_policy) +#define F2FS_IOC_GET_ENCRYPTION_PWSALT \ + _IOW('f', 20, __u8[16]) +#define F2FS_IOC_GET_ENCRYPTION_POLICY \ + _IOW('f', 21, struct f2fs_encryption_policy) +/* * should be same as XFS_IOC_GOINGDOWN. * Flags for going down operation used by FS_IOC_GOINGDOWN
@@ -367,6 +374,8 @@ struct f2fs_map_blocks {#define F2FS_ENCRYPTION_MODE_AES_256_CBC 3#define F2FS_ENCRYPTION_MODE_AES_256_CTS 4 +#include "f2fs_crypto.h" +#define DEF_DIR_LEVEL 0struct f2fs_inode_info {
@@ -1945,4 +1954,11 @@ static inline int f2fs_sb_has_crypto(struct super_block *sb)#else return 0 ;#endif + +/* crypto_policy.c */ +int f2fs_is_child_context_consistent_with_parent (struct inode *, +struct inode *); +int f2fs_inherit_context (struct inode *,struct inode *,struct page *); +int f2fs_process_policy (const struct f2fs_encryption_policy *,struct inode *); +int f2fs_get_policy (struct inode *,struct f2fs_encryption_policy *);#endif
fs/f2fs/file.c +91 -0
109 lines not on this page · raw message
fs/f2fs/xattr.c +3 -0
@@ -584,6 +584,9 @@ static int __f2fs_setxattr(struct inode *inode, int index, inode->i_ctime =CURRENT_TIME ;clear_inode_flag (fi,FI_ACL_MODE ); } +if (index ==F2FS_XATTR_INDEX_ENCRYPTION && + !strcmp (name,F2FS_XATTR_NAME_ENCRYPTION_CONTEXT )) +f2fs_set_encrypted_inode (inode);if (ipage)update_inode (inode, ipage);
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 7/18 f2fs crypto: add f2fs encryption facilities
In reply to Jaegeuk KimMost of parts were copied from ext4, except:
- add f2fs_restore_and_release_control_page which returns control page and restore control page
- remove ext4_encrypted_zeroout()
- remove sbi->s_file_encryption_mode & sbi->s_dir_encryption_mode
- add f2fs_end_io_crypto_work for mpage_end_io
- set num_prealloc_crypto_pages to 128, max size for one bio
- call f2fs_exit_crypto() in put_super
- call f2fs_init_crypto() in fill_super to avoid runtime GFP_KERNEL allocation in writepage path
--- fs/f2fs/Makefile | 2 +- fs/f2fs/crypto.c | 561 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/f2fs/f2fs.h | 25 +++ fs/f2fs/super.c | 19 +- 4 files changed, 603 insertions(+), 4 deletions(-) create mode 100644 fs/f2fs/crypto.c
fs/f2fs/Makefile +1 -1
@@ -6,4 +6,4 @@ f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o f2fs-$(CONFIG_F2FS_IO_TRACE) += trace.o -f2fs-$(CONFIG_F2FS_FS_ENCRYPTION) += crypto_policy.o +f2fs-$(CONFIG_F2FS_FS_ENCRYPTION) += crypto_policy.o crypto.o
fs/f2fs/crypto.c new file +561 -0
561 lines not on this page · raw message
fs/f2fs/f2fs.h +25 -0
@@ -1954,6 +1954,7 @@ static inline int f2fs_sb_has_crypto(struct super_block *sb)#else return 0 ;#endif +}/* crypto_policy.c */ int f2fs_is_child_context_consistent_with_parent(struct inode *,
@@ -1961,4 +1962,28 @@ int f2fs_is_child_context_consistent_with_parent(struct inode *,int f2fs_inherit_context (struct inode *,struct inode *,struct page *);int f2fs_process_policy (const struct f2fs_encryption_policy *,struct inode *);int f2fs_get_policy (struct inode *,struct f2fs_encryption_policy *); + +/* crypt.c */ +bool f2fs_valid_contents_enc_mode (uint32_t ); +uint32_t f2fs_validate_encryption_key_size (uint32_t ,uint32_t ); +struct f2fs_crypto_ctx *f2fs_get_crypto_ctx (struct inode *); +void f2fs_release_crypto_ctx (struct f2fs_crypto_ctx *); +struct page *f2fs_encrypt (struct inode *,struct page *); +int f2fs_decrypt (struct f2fs_crypto_ctx *,struct page *); +int f2fs_decrypt_one (struct inode *,struct page *); +void f2fs_end_io_crypto_work (struct f2fs_crypto_ctx *,struct bio *); + +#ifdef CONFIG_F2FS_FS_ENCRYPTION +void f2fs_restore_and_release_control_page (struct page **); +void f2fs_restore_control_page (struct page *); + +int f2fs_init_crypto (void ); +void f2fs_exit_crypto (void ); +#else +static inline void f2fs_restore_and_release_control_page (struct page **p) { } +static inline void f2fs_restore_control_page (struct page *p) { } + +static inline int f2fs_init_crypto (void ) {return 0 ; } +static inline void f2fs_exit_crypto (void ) { } +#endif #endif
fs/f2fs/super.c +16 -3
@@ -416,6 +416,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)/* Will be used by directory only */ fi->i_dir_level =F2FS_SB (sb)->dir_level; +#ifdef CONFIG_F2FS_FS_ENCRYPTION + fi->i_crypt_info =NULL ; +#endif return &fi->vfs_inode; }
@@ -494,6 +497,9 @@ static void f2fs_put_super(struct super_block *sb)destroy_node_manager (sbi);destroy_segment_manager (sbi); +/* destroy crypto buffers */ +f2fs_exit_crypto (); +kfree (sbi->ckpt);kobject_put (&sbi->s_kobj);wait_for_completion (&sbi->s_kobj_unregister);
@@ -1187,6 +1193,11 @@ try_onemore:if (err) goto free_proc; +/* init crypto buffers */ + err =f2fs_init_crypto (); +if (err) + goto free_kobj; +/* recover fsynced data */ if (!test_opt (sbi,DISABLE_ROLL_FORWARD )) {/*
@@ -1196,7 +1207,7 @@ try_onemore:if (bdev_read_only (sb->s_bdev) && !is_set_ckpt_flags (sbi->ckpt,CP_UMOUNT_FLAG )) { err = -EROFS ; - goto free_kobj; + goto free_crypto; }if (need_fsck)
@@ -1207,7 +1218,7 @@ try_onemore: need_fsck = true;f2fs_msg (sb,KERN_ERR ,"Cannot recover all fsync data errno=%ld" , err); - goto free_kobj; + goto free_crypto; } }
@@ -1219,11 +1230,13 @@ try_onemore:/* After POR, we can run background GC thread.*/ err =start_gc_thread (sbi);if (err) - goto free_kobj; + goto free_crypto; }kfree (options);return 0 ; +free_crypto: +f2fs_exit_crypto (); free_kobj:kobject_del (&sbi->s_kobj); free_proc:
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 8/18 f2fs crypto: add encryption key management facilities
In reply to Jaegeuk KimThis patch copies from encrypt_key.c in ext4, and modifies for f2fs.
Use GFP_NOFS, since _f2fs_get_encryption_info is called under f2fs_lock_op.
--- fs/f2fs/Makefile | 2 +- fs/f2fs/crypto_key.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/f2fs/f2fs.h | 22 ++++++ fs/f2fs/f2fs_crypto.h | 3 + 4 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 fs/f2fs/crypto_key.c
fs/f2fs/Makefile +1 -1
@@ -6,4 +6,4 @@ f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o f2fs-$(CONFIG_F2FS_IO_TRACE) += trace.o -f2fs-$(CONFIG_F2FS_FS_ENCRYPTION) += crypto_policy.o crypto.o +f2fs-$(CONFIG_F2FS_FS_ENCRYPTION) += crypto_policy.o crypto.o crypto_key.o
fs/f2fs/crypto_key.c new file +200 -0
200 lines not on this page · raw message
fs/f2fs/f2fs.h +22 -0
@@ -1973,17 +1973,39 @@ int f2fs_decrypt(struct f2fs_crypto_ctx *, struct page *);int f2fs_decrypt_one (struct inode *,struct page *);void f2fs_end_io_crypto_work (struct f2fs_crypto_ctx *,struct bio *); +/* crypto_key.c */ +void f2fs_free_encryption_info (struct inode *); +int _f2fs_get_encryption_info (struct inode *inode); +#ifdef CONFIG_F2FS_FS_ENCRYPTION void f2fs_restore_and_release_control_page (struct page **);void f2fs_restore_control_page (struct page *);int f2fs_init_crypto (void );void f2fs_exit_crypto (void ); + +int f2fs_has_encryption_key (struct inode *); + +static inline int f2fs_get_encryption_info (struct inode *inode) +{ +struct f2fs_crypt_info *ci =F2FS_I (inode)->i_crypt_info; + +if (!ci || + (ci->ci_keyring_key && + (ci->ci_keyring_key->flags & ((1 <<KEY_FLAG_INVALIDATED ) | + (1 <<KEY_FLAG_REVOKED ) | + (1 <<KEY_FLAG_DEAD ))))) +return _f2fs_get_encryption_info (inode); +return 0 ; +}#else static inline void f2fs_restore_and_release_control_page (struct page **p) { }static inline void f2fs_restore_control_page (struct page *p) { }static inline int f2fs_init_crypto (void ) {return 0 ; }static inline void f2fs_exit_crypto (void ) { } + +static inline int f2fs_has_encryption_key (struct inode *i) {return 0 ; } +static inline int f2fs_get_encryption_info (struct inode *i) {return 0 ; }#endif #endif
fs/f2fs/f2fs_crypto.h +3 -0
@@ -65,6 +65,9 @@ struct f2fs_encryption_context {#define F2FS_AES_256_XTS_KEY_SIZE 64#define F2FS_MAX_KEY_SIZE 64 +#define F2FS_KEY_DESC_PREFIX "f2fs:" +#define F2FS_KEY_DESC_PREFIX_SIZE 5 +struct f2fs_encryption_key {__u32 mode;char raw[F2FS_MAX_KEY_SIZE ];
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 9/18 f2fs crypto: filename encryption facilities
In reply to Jaegeuk KimThis patch adds filename encryption infra.
Most of codes are copied from ext4 part, but changed to adjust f2fs directory structure.
--- fs/f2fs/Makefile | 3 +- fs/f2fs/crypto_fname.c | 490 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/f2fs/f2fs.h | 52 ++++++ 3 files changed, 544 insertions(+), 1 deletion(-) create mode 100644 fs/f2fs/crypto_fname.c
fs/f2fs/Makefile +2 -1
@@ -6,4 +6,5 @@ f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o f2fs-$(CONFIG_F2FS_IO_TRACE) += trace.o -f2fs-$(CONFIG_F2FS_FS_ENCRYPTION) += crypto_policy.o crypto.o crypto_key.o +f2fs-$(CONFIG_F2FS_FS_ENCRYPTION) += crypto_policy.o crypto.o \ + crypto_key.o crypto_fname.o
fs/f2fs/crypto_fname.c new file +490 -0
490 lines not on this page · raw message
fs/f2fs/f2fs.h +52 -0
75 lines not on this page · raw message
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 10/18 f2fs crypto: activate encryption support for fs APIs
In reply to Jaegeuk KimThis patch activates the following APIs for encryption support.
The rules quoted by ext4 are:
- An unencrypted directory may contain encrypted or unencrypted files or directories.
- All files or directories in a directory must be protected using the same key as their containing directory.
- Encrypted inode for regular file should not have inline_data.
- Encrypted symlink and directory may have inline_data and inline_dentry.
This patch activates the following APIs.
1. f2fs_link : validate context 2. f2fs_lookup : '' 3. f2fs_rename : '' 4. f2fs_create/f2fs_mkdir : inherit its dir's context 5. f2fs_direct_IO : do buffered io for regular files 6. f2fs_open : check encryption info 7. f2fs_file_mmap : '' 8. f2fs_setattr : '' 9. f2fs_file_write_iter : '' (Called by sys_io_submit)
--- fs/f2fs/data.c | 3 +++ fs/f2fs/dir.c | 6 ++++++ fs/f2fs/f2fs.h | 11 +++++++++++ fs/f2fs/file.c | 34 ++++++++++++++++++++++++++++++++-- fs/f2fs/inline.c | 3 +++ fs/f2fs/namei.c | 38 ++++++++++++++++++++++++++++++++------ 6 files changed, 87 insertions(+), 8 deletions(-)
fs/f2fs/data.c +3 -0
@@ -1982,6 +1982,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,return err; } +if (f2fs_encrypted_inode (inode) &&S_ISREG (inode->i_mode)) +return 0 ; +if (check_direct_IO (inode, iter, offset))return 0 ;
fs/f2fs/dir.c +6 -0
@@ -390,6 +390,12 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir, err =f2fs_init_security (inode, dir, name, page);if (err) goto put_error; + +if (f2fs_encrypted_inode (dir) &&f2fs_may_encrypt (inode)) { + err =f2fs_inherit_context (dir, inode, page); +if (err) + goto put_error; + } }else { page =get_node_page (F2FS_I_SB (dir), inode->i_ino);if (IS_ERR (page))
fs/f2fs/f2fs.h +11 -0
@@ -1975,6 +1975,17 @@ static inline int f2fs_sb_has_crypto(struct super_block *sb)#endif } +static inline bool f2fs_may_encrypt (struct inode *inode) +{ +#ifdef CONFIG_F2FS_FS_ENCRYPTION +mode_t mode = inode->i_mode; + +return (S_ISREG (mode) ||S_ISDIR (mode) ||S_ISLNK (mode)); +#else +return 0 ; +#endif +} +/* crypto_policy.c */ int f2fs_is_child_context_consistent_with_parent (struct inode *,struct inode *);
fs/f2fs/file.c +32 -2
@@ -408,6 +408,12 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma) {struct inode *inode =file_inode (file); +if (f2fs_encrypted_inode (inode)) { +int err =f2fs_get_encryption_info (inode); +if (err) +return 0 ; + } +/* we don't need to use inline_data strictly */ if (f2fs_has_inline_data (inode)) {int err =f2fs_convert_inline_inode (inode);
@@ -420,6 +426,14 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)return 0 ; } +static int f2fs_file_open (struct inode *inode,struct file *filp) +{ +if (f2fs_encrypted_inode (inode) &&f2fs_get_encryption_info (inode)) +return -EACCES ; + +return generic_file_open (inode, filp); +} +int truncate_data_blocks_range (struct dnode_of_data *dn,int count) {int nr_free =0 , ofs = dn->ofs_in_node;
@@ -627,6 +641,10 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)return err;if (attr->ia_valid &ATTR_SIZE ) { +if (f2fs_encrypted_inode (inode) && +f2fs_get_encryption_info (inode)) +return -EACCES ; +if (attr->ia_size !=i_size_read (inode)) {truncate_setsize (inode, attr->ia_size);f2fs_truncate (inode);
@@ -1466,6 +1484,18 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } +static ssize_t f2fs_file_write_iter (struct kiocb *iocb,struct iov_iter *from) +{ +struct inode *inode =file_inode (iocb->ki_filp); + +if (f2fs_encrypted_inode (inode) && + !f2fs_has_encryption_key (inode) && +f2fs_get_encryption_info (inode)) +return -EACCES ; + +return generic_file_write_iter (iocb, from); +} +#ifdef CONFIG_COMPAT long f2fs_compat_ioctl (struct file *file,unsigned int cmd,unsigned long arg) {
@@ -1486,8 +1516,8 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)const struct file_operations f2fs_file_operations = { .llseek = f2fs_llseek, .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, - .open = generic_file_open, + .write_iter = f2fs_file_write_iter, + .open = f2fs_file_open, .release = f2fs_release_file, .mmap = f2fs_file_mmap, .fsync = f2fs_sync_file,
fs/f2fs/inline.c +3 -0
@@ -27,6 +27,9 @@ bool f2fs_may_inline_data(struct inode *inode)if (i_size_read (inode) >MAX_INLINE_DATA )return false; +if (f2fs_encrypted_inode (inode) &&S_ISREG (inode->i_mode)) +return false; +return true; }
fs/f2fs/namei.c +32 -6
@@ -56,6 +56,10 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) goto out; } +/* If the directory encrypted, then we should encrypt the inode. */ +if (f2fs_encrypted_inode (dir) &&f2fs_may_encrypt (inode)) +f2fs_set_encrypted_inode (inode); +if (f2fs_may_inline_data (inode))set_inode_flag (F2FS_I (inode),FI_INLINE_DATA );if (f2fs_may_inline_dentry (inode))
@@ -157,6 +161,10 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,struct f2fs_sb_info *sbi =F2FS_I_SB (dir);int err; +if (f2fs_encrypted_inode (dir) && + !f2fs_is_child_context_consistent_with_parent (dir, inode)) +return -EPERM ; +f2fs_balance_fs (sbi); inode->i_ctime =CURRENT_TIME ;
@@ -235,6 +243,7 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,struct f2fs_dir_entry *de;struct page *page;nid_t ino; +int err =0 ;if (dentry->d_name.len >F2FS_NAME_LEN )return ERR_PTR (-ENAMETOOLONG );
@@ -251,16 +260,26 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,if (IS_ERR (inode))return ERR_CAST (inode); -if (f2fs_has_inline_dots (inode)) { -int err; +if (f2fs_encrypted_inode (dir) &&f2fs_may_encrypt (inode) && + !f2fs_is_child_context_consistent_with_parent (dir, inode)) { +iput (inode); +f2fs_msg (inode->i_sb,KERN_WARNING , +"Inconsistent encryption contexts: %lu/%lu\n" , + (unsigned long )dir->i_ino, + (unsigned long )inode->i_ino); +return ERR_PTR (-EPERM ); + } +if (f2fs_has_inline_dots (inode)) { err =__recover_dot_dentries (inode, dir->i_ino); -if (err) { -iget_failed (inode); -return ERR_PTR (err); - } +if (err) + goto err_out; }return d_splice_alias (inode, dentry); + +err_out: +iget_failed (inode); +return ERR_PTR (err); }static int f2fs_unlink (struct inode *dir,struct dentry *dentry)
@@ -460,6 +479,13 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,struct f2fs_dir_entry *new_entry;int err = -ENOENT ; +if ((old_dir != new_dir) &&f2fs_encrypted_inode (new_dir) && + !f2fs_is_child_context_consistent_with_parent (new_dir, + old_inode)) { + err = -EPERM ; + goto out; + } +f2fs_balance_fs (sbi); old_entry =f2fs_find_entry (old_dir, &old_dentry->d_name, &old_page);
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 11/18 f2fs crypto: add encryption support in read/write paths
In reply to Jaegeuk KimThis patch adds encryption support in read and write paths.
Note that, in f2fs, we need to consider cleaning operation.
In cleaning procedure, we must avoid encrypting and decrypting written blocks. So, this patch implements move_encrypted_block().
--- fs/f2fs/checkpoint.c | 4 ++- fs/f2fs/data.c | 96 ++++++++++++++++++++++++++++++++++++++++------------ fs/f2fs/f2fs.h | 1 + fs/f2fs/file.c | 2 +- fs/f2fs/gc.c | 79 +++++++++++++++++++++++++++++++++++++++++- fs/f2fs/inline.c | 1 + fs/f2fs/node.c | 2 ++ fs/f2fs/segment.c | 24 ++++++++++--- 8 files changed, 180 insertions(+), 29 deletions(-)
fs/f2fs/checkpoint.c +3 -1
@@ -56,6 +56,7 @@ struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) .type = META, .rw = READ_SYNC | REQ_META | REQ_PRIO, .blk_addr = index, + .encrypted_page = NULL, }; repeat: page =grab_cache_page (mapping, index);
@@ -122,7 +123,8 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, int typestruct f2fs_io_info fio = { .sbi = sbi, .type =META , - .rw =READ_SYNC |REQ_META |REQ_PRIO + .rw =READ_SYNC |REQ_META |REQ_PRIO , + .encrypted_page =NULL , };for (; nrpages-- >0 ; blkno++) {
fs/f2fs/data.c +74 -22
184 lines not on this page · raw message
fs/f2fs/f2fs.h +1 -0
@@ -656,6 +656,7 @@ struct f2fs_io_info {int rw;/* contains R/RS/W/WS with REQ_META/REQ_PRIO */ block_t blk_addr;/* block address to be written */ struct page *page;/* page to be written */ +struct page *encrypted_page;/* encrypted page */ };#define is_read_io (rw) (((rw) & 1) == READ)
fs/f2fs/file.c +1 -1
@@ -500,7 +500,7 @@ static int truncate_partial_data_page(struct inode *inode, u64 from, truncate_out:f2fs_wait_on_page_writeback (page,DATA );zero_user (page, offset,PAGE_CACHE_SIZE - offset); -if (!cache_only) +if (!cache_only || !f2fs_encrypted_inode (inode) || !S_ISREG (inode->i_mode))set_page_dirty (page);f2fs_put_page (page,1 );return 0 ;
fs/f2fs/gc.c +78 -1
103 lines not on this page · raw message
fs/f2fs/inline.c +1 -0
@@ -113,6 +113,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) .type = DATA, .rw = WRITE_SYNC | REQ_PRIO, .page = page, + .encrypted_page = NULL, };int dirty, err;
fs/f2fs/node.c +2 -0
@@ -1003,6 +1003,7 @@ static int read_node_page(struct page *page, int rw) .type = NODE, .rw = rw, .page = page, + .encrypted_page = NULL, };get_node_info (sbi, page->index, &ni);
@@ -1299,6 +1300,7 @@ static int f2fs_write_node_page(struct page *page, .type = NODE, .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE, .page = page, + .encrypted_page = NULL, };trace_f2fs_writepage (page,NODE );
fs/f2fs/segment.c +20 -4
@@ -219,6 +219,7 @@ void commit_inmem_pages(struct inode *inode, bool abort) .sbi = sbi, .type = DATA, .rw = WRITE_SYNC | REQ_PRIO, + .encrypted_page = NULL, };/*
@@ -1246,6 +1247,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) .rw = WRITE_SYNC | REQ_META | REQ_PRIO, .blk_addr = page->index, .page = page, + .encrypted_page = NULL, };set_page_writeback (page);
@@ -1345,20 +1347,34 @@ static inline bool is_merged_page(struct f2fs_sb_info *sbi,enum page_type btype =PAGE_TYPE_OF_BIO (type);struct f2fs_bio_info *io = &sbi->write_io[btype];struct bio_vec *bvec; +struct page *target;int i;down_read (&io->io_rwsem); -if (!io->bio) - goto out; +if (!io->bio) { +up_read (&io->io_rwsem); +return false; + }bio_for_each_segment_all (bvec, io->bio, i) { -if (page == bvec->bv_page) { + +if (bvec->bv_page->mapping) { + target = bvec->bv_page; + }else { +struct f2fs_crypto_ctx *ctx; + +/* encrypted page */ + ctx = (struct f2fs_crypto_ctx *)page_private ( + bvec->bv_page); + target = ctx->control_page; + } + +if (page == target) {up_read (&io->io_rwsem);return true; } } -out:up_read (&io->io_rwsem);return false; }
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 12/18 f2fs crypto: add filename encryption for f2fs_add_link
In reply to Jaegeuk KimThis patch adds filename encryption support for f2fs_add_link.
--- fs/f2fs/dir.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-)
fs/f2fs/dir.c +27 -12
@@ -507,24 +507,33 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,unsigned long bidx, block;f2fs_hash_t dentry_hash;unsigned int nbucket, nblock; -size_t namelen = name->len;struct page *dentry_page =NULL ;struct f2fs_dentry_block *dentry_blk =NULL ;struct f2fs_dentry_ptr d; -int slots =GET_DENTRY_SLOTS (namelen);struct page *page =NULL ; -int err =0 ; +struct f2fs_filename fname; +struct qstr new_name; +int slots, err; + + err =f2fs_fname_setup_filename (dir, name,0 , &fname); +if (err) +return err; + + new_name.name =fname_name (&fname); + new_name.len =fname_len (&fname);if (f2fs_has_inline_dentry (dir)) { - err =f2fs_add_inline_entry (dir, name, inode, ino, mode); + err =f2fs_add_inline_entry (dir, &new_name, inode, ino, mode);if (!err || err != -EAGAIN ) -return err; + goto out;else err =0 ; } - dentry_hash =f2fs_dentry_hash (name); level =0 ; + slots =GET_DENTRY_SLOTS (new_name.len); + dentry_hash =f2fs_dentry_hash (&new_name); + current_depth =F2FS_I (dir)->i_current_depth;if (F2FS_I (dir)->chash == dentry_hash) { level =F2FS_I (dir)->clevel;
@@ -532,8 +541,10 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, } start: -if (unlikely (current_depth ==MAX_DIR_HASH_DEPTH )) -return -ENOSPC ; +if (unlikely (current_depth ==MAX_DIR_HASH_DEPTH )) { + err = -ENOSPC ; + goto out; + }/* Increase the depth, if required */ if (level == current_depth)
@@ -547,8 +558,10 @@ start:for (block = bidx; block <= (bidx + nblock -1 ); block++) { dentry_page =get_new_data_page (dir,NULL , block, true); -if (IS_ERR (dentry_page)) -return PTR_ERR (dentry_page); +if (IS_ERR (dentry_page)) { + err =PTR_ERR (dentry_page); + goto out; + } dentry_blk =kmap (dentry_page); bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
@@ -568,7 +581,7 @@ add_dentry:if (inode) {down_write (&F2FS_I (inode)->i_sem); - page =init_inode_metadata (inode, dir, name,NULL ); + page =init_inode_metadata (inode, dir, &new_name,NULL );if (IS_ERR (page)) { err =PTR_ERR (page); goto fail;
@@ -576,7 +589,7 @@ add_dentry: }make_dentry_ptr (&d, (void *)dentry_blk,1 ); -f2fs_update_dentry (ino, mode, &d, name, dentry_hash, bit_pos); +f2fs_update_dentry (ino, mode, &d, &new_name, dentry_hash, bit_pos);set_page_dirty (dentry_page);
@@ -598,6 +611,8 @@ fail: }kunmap (dentry_page);f2fs_put_page (dentry_page,1 ); +out: +f2fs_fname_free_filename (&fname);return err; }
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 13/18 f2fs crypto: add filename encryption for f2fs_readdir
In reply to Jaegeuk KimThis patch implements filename encryption support for f2fs_readdir.
--- fs/f2fs/dir.c | 57 ++++++++++++++++++++++++++++++++++++++++++++------------ fs/f2fs/f2fs.h | 12 ++++++++---- fs/f2fs/inline.c | 13 +++++++------ 3 files changed, 60 insertions(+), 22 deletions(-)
fs/f2fs/dir.c +45 -12
@@ -98,7 +98,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, dentry_blk = (struct f2fs_dentry_block *)kmap (dentry_page); -make_dentry_ptr (&d, (void *)dentry_blk,1 ); +make_dentry_ptr (NULL , &d, (void *)dentry_blk,1 ); de =find_target_dentry (name, max_slots, &d);if (de)
@@ -356,7 +356,7 @@ static int make_empty_dir(struct inode *inode, dentry_blk =kmap_atomic (dentry_page); -make_dentry_ptr (&d, (void *)dentry_blk,1 ); +make_dentry_ptr (NULL , &d, (void *)dentry_blk,1 );do_make_empty_dir (inode, parent, &d);kunmap_atomic (dentry_blk);
@@ -588,7 +588,7 @@ add_dentry: } } -make_dentry_ptr (&d, (void *)dentry_blk,1 ); +make_dentry_ptr (NULL , &d, (void *)dentry_blk,1 );f2fs_update_dentry (ino, mode, &d, &new_name, dentry_hash, bit_pos);set_page_dirty (dentry_page);
@@ -750,11 +750,12 @@ bool f2fs_empty_dir(struct inode *dir) }bool f2fs_fill_dentries (struct dir_context *ctx,struct f2fs_dentry_ptr *d, -unsigned int start_pos) +unsigned int start_pos,struct f2fs_str *fstr) {unsigned char d_type =DT_UNKNOWN ;unsigned int bit_pos;struct f2fs_dir_entry *de =NULL ; +struct f2fs_str de_name =FSTR_INIT (NULL ,0 ); bit_pos = ((unsigned long )ctx->pos % d->max);
@@ -768,8 +769,24 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, d_type = f2fs_filetype_table[de->file_type]; else d_type =DT_UNKNOWN ; -if (!dir_emit (ctx, d->filename[bit_pos], -le16_to_cpu (de->name_len), + +/* encrypted case */ + de_name.name = d->filename[bit_pos]; + de_name.len =le16_to_cpu (de->name_len); + +if (f2fs_encrypted_inode (d->inode)) { +int save_len = fstr->len; +int ret; + + ret =f2fs_fname_disk_to_usr (d->inode, &de->hash_code, + &de_name, fstr); + de_name = *fstr; + fstr->len = save_len; +if (ret <0 ) +return true; + } + +if (!dir_emit (ctx, de_name.name, de_name.len,le32_to_cpu (de->ino), d_type))return true;
@@ -788,9 +805,24 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)struct file_ra_state *ra = &file->f_ra;unsigned int n = ((unsigned long )ctx->pos /NR_DENTRY_IN_BLOCK );struct f2fs_dentry_ptr d; +struct f2fs_str fstr =FSTR_INIT (NULL ,0 ); +int err =0 ; -if (f2fs_has_inline_dentry (inode)) -return f2fs_read_inline_dir (file, ctx); + err =f2fs_setup_fname_crypto (inode); +if (err) +return err; + +if (f2fs_encrypted_inode (inode)) { + err =f2fs_fname_crypto_alloc_buffer (inode,F2FS_NAME_LEN , + &fstr); +if (err <0 ) +return err; + } + +if (f2fs_has_inline_dentry (inode)) { + err =f2fs_read_inline_dir (file, ctx, &fstr); + goto out; + }/* readahead for multi pages of dir */ if (npages - n >1 && !ra_has_index (ra, n))
@@ -804,9 +836,9 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) dentry_blk =kmap (dentry_page); -make_dentry_ptr (&d, (void *)dentry_blk,1 ); +make_dentry_ptr (inode, &d, (void *)dentry_blk,1 ); -if (f2fs_fill_dentries (ctx, &d, n *NR_DENTRY_IN_BLOCK )) +if (f2fs_fill_dentries (ctx, &d, n *NR_DENTRY_IN_BLOCK , &fstr)) goto stop; ctx->pos = (n +1 ) *NR_DENTRY_IN_BLOCK ;
@@ -819,8 +851,9 @@ stop:kunmap (dentry_page);f2fs_put_page (dentry_page,1 ); } - -return 0 ; +out: +f2fs_fname_crypto_free_buffer (&fstr); +return err; }const struct file_operations f2fs_dir_operations = {
fs/f2fs/f2fs.h +8 -4
@@ -277,15 +277,18 @@ struct f2fs_filename {#define fname_len (p) ((p)->disk_name.len)struct f2fs_dentry_ptr { +struct inode *inode;const void *bitmap;struct f2fs_dir_entry *dentry;__u8 (*filename)[F2FS_SLOT_LEN ];int max; }; -static inline void make_dentry_ptr (struct f2fs_dentry_ptr *d, -void *src,int type) +static inline void make_dentry_ptr (struct inode *inode, +struct f2fs_dentry_ptr *d,void *src,int type) { + d->inode = inode; +if (type ==1 ) {struct f2fs_dentry_block *t = (struct f2fs_dentry_block *)src; d->max =NR_DENTRY_IN_BLOCK ;
@@ -1584,7 +1587,7 @@ void set_de_type(struct f2fs_dir_entry *, umode_t);struct f2fs_dir_entry *find_target_dentry (struct qstr *,int *,struct f2fs_dentry_ptr *);bool f2fs_fill_dentries (struct dir_context *,struct f2fs_dentry_ptr *, -unsigned int ); +unsigned int ,struct f2fs_str *);void do_make_empty_dir (struct inode *,struct inode *,struct f2fs_dentry_ptr *); struct page *init_inode_metadata(struct inode *, struct inode *,
@@ -1937,7 +1940,8 @@ int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,void f2fs_delete_inline_entry (struct f2fs_dir_entry *,struct page *,struct inode *,struct inode *);bool f2fs_empty_inline_dir (struct inode *); -int f2fs_read_inline_dir (struct file *,struct dir_context *); +int f2fs_read_inline_dir (struct file *,struct dir_context *, +struct f2fs_str *);/* * crypto support
fs/f2fs/inline.c +7 -6
@@ -298,7 +298,7 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, inline_dentry =inline_data_addr (ipage); -make_dentry_ptr (&d, (void *)inline_dentry,2 ); +make_dentry_ptr (NULL , &d, (void *)inline_dentry,2 ); de =find_target_dentry (name,NULL , &d);unlock_page (ipage);
@@ -342,7 +342,7 @@ int make_empty_inline_dir(struct inode *inode, struct inode *parent, dentry_blk =inline_data_addr (ipage); -make_dentry_ptr (&d, (void *)dentry_blk,2 ); +make_dentry_ptr (NULL , &d, (void *)dentry_blk,2 );do_make_empty_dir (inode, parent, &d);set_page_dirty (ipage);
@@ -446,7 +446,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,f2fs_wait_on_page_writeback (ipage,NODE ); name_hash =f2fs_dentry_hash (name); -make_dentry_ptr (&d, (void *)dentry_blk,2 ); +make_dentry_ptr (NULL , &d, (void *)dentry_blk,2 );f2fs_update_dentry (ino, mode, &d, name, name_hash, bit_pos);set_page_dirty (ipage);
@@ -523,7 +523,8 @@ bool f2fs_empty_inline_dir(struct inode *dir)return true; } -int f2fs_read_inline_dir (struct file *file,struct dir_context *ctx) +int f2fs_read_inline_dir (struct file *file,struct dir_context *ctx, +struct f2fs_str *fstr) {struct inode *inode =file_inode (file);struct f2fs_inline_dentry *inline_dentry =NULL ;
@@ -539,9 +540,9 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx) inline_dentry =inline_data_addr (ipage); -make_dentry_ptr (&d, (void *)inline_dentry,2 ); +make_dentry_ptr (inode, &d, (void *)inline_dentry,2 ); -if (!f2fs_fill_dentries (ctx, &d,0 )) +if (!f2fs_fill_dentries (ctx, &d,0 , fstr)) ctx->pos =NR_INLINE_DENTRY ;f2fs_put_page (ipage,1 );
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 14/18 f2fs crypto: add filename encryption for f2fs_lookup
In reply to Jaegeuk KimThis patch implements filename encryption support for f2fs_lookup.
Note that, f2fs_find_entry should be outside of f2fs_(un)lock_op().
--- fs/f2fs/dir.c | 79 ++++++++++++++++++++++++++++++++------------------------ fs/f2fs/f2fs.h | 9 ++++--- fs/f2fs/inline.c | 9 ++++--- 3 files changed, 56 insertions(+), 41 deletions(-)
fs/f2fs/dir.c +45 -34
@@ -76,20 +76,10 @@ static unsigned long dir_block_index(unsigned int level,return bidx; } -static bool early_match_name (size_t namelen,f2fs_hash_t namehash, -struct f2fs_dir_entry *de) -{ -if (le16_to_cpu (de->name_len) != namelen) -return false; - -if (de->hash_code != namehash) -return false; - -return true; -} -static struct f2fs_dir_entry *find_in_block (struct page *dentry_page, -struct qstr *name,int *max_slots, +struct f2fs_filename *fname, +f2fs_hash_t namehash, +int *max_slots,struct page **res_page) {struct f2fs_dentry_block *dentry_blk;
@@ -99,8 +89,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, dentry_blk = (struct f2fs_dentry_block *)kmap (dentry_page);make_dentry_ptr (NULL , &d, (void *)dentry_blk,1 ); - de =find_target_dentry (name, max_slots, &d); - + de =find_target_dentry (fname, namehash, max_slots, &d);if (de) *res_page = dentry_page;else
@@ -114,13 +103,15 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,return de; } -struct f2fs_dir_entry *find_target_dentry (struct qstr *name,int *max_slots, -struct f2fs_dentry_ptr *d) +struct f2fs_dir_entry *find_target_dentry (struct f2fs_filename *fname, +f2fs_hash_t namehash,int *max_slots, +struct f2fs_dentry_ptr *d) {struct f2fs_dir_entry *de;unsigned long bit_pos =0 ; -f2fs_hash_t namehash =f2fs_dentry_hash (name);int max_len =0 ; +struct f2fs_str de_name =FSTR_INIT (NULL ,0 ); +struct f2fs_str *name = &fname->disk_name;if (max_slots) *max_slots =0 ;
@@ -132,8 +123,18 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, } de = &d->dentry[bit_pos]; -if (early_match_name (name->len, namehash, de) && - !memcmp (d->filename[bit_pos], name->name, name->len)) + +/* encrypted case */ + de_name.name = d->filename[bit_pos]; + de_name.len =le16_to_cpu (de->name_len); + +/* show encrypted name */ +if (fname->hash) { +if (de->hash_code == fname->hash) + goto found; + }else if (de_name.len == name->len && + de->hash_code == namehash && + !memcmp (de_name.name, name->name, name->len)) goto found;if (max_slots && max_len > *max_slots)
@@ -155,16 +156,21 @@ found: }static struct f2fs_dir_entry *find_in_level (struct inode *dir, -unsigned int level,struct qstr *name, -f2fs_hash_t namehash,struct page **res_page) +unsigned int level, +struct f2fs_filename *fname, +struct page **res_page) { -int s =GET_DENTRY_SLOTS (name->len); +struct qstr name =FSTR_TO_QSTR (&fname->disk_name); +int s =GET_DENTRY_SLOTS (name.len);unsigned int nbucket, nblock;unsigned int bidx, end_block;struct page *dentry_page;struct f2fs_dir_entry *de =NULL ;bool room = false;int max_slots; +f2fs_hash_t namehash; + + namehash =f2fs_dentry_hash (&name);f2fs_bug_on (F2FS_I_SB (dir), level >MAX_DIR_HASH_DEPTH );
@@ -183,7 +189,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,continue ; } - de =find_in_block (dentry_page, name, &max_slots, res_page); + de =find_in_block (dentry_page, fname, namehash, &max_slots, + res_page);if (de)break ;
@@ -211,30 +218,34 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, {unsigned long npages =dir_blocks (dir);struct f2fs_dir_entry *de =NULL ; -f2fs_hash_t name_hash;unsigned int max_depth;unsigned int level; +struct f2fs_filename fname; +int err; *res_page =NULL ; -if (f2fs_has_inline_dentry (dir)) -return find_in_inline_dir (dir, child, res_page); + err =f2fs_fname_setup_filename (dir, child,1 , &fname); +if (err) +return NULL ; + +if (f2fs_has_inline_dentry (dir)) { + de =find_in_inline_dir (dir, &fname, res_page); + goto out; + }if (npages ==0 ) -return NULL ; + goto out; - name_hash =f2fs_dentry_hash (child); max_depth =F2FS_I (dir)->i_current_depth;for (level =0 ; level < max_depth; level++) { - de =find_in_level (dir, level, child, name_hash, res_page); + de =find_in_level (dir, level, &fname, res_page);if (de)break ; } -if (!de &&F2FS_I (dir)->chash != name_hash) { -F2FS_I (dir)->chash = name_hash; -F2FS_I (dir)->clevel = level -1 ; - } +out: +f2fs_fname_free_filename (&fname);return de; }
fs/f2fs/f2fs.h +5 -4
@@ -1584,8 +1584,9 @@ struct dentry *f2fs_get_parent(struct dentry *child);*/ extern unsigned char f2fs_filetype_table[F2FS_FT_MAX ];void set_de_type (struct f2fs_dir_entry *,umode_t ); -struct f2fs_dir_entry *find_target_dentry (struct qstr *,int *, -struct f2fs_dentry_ptr *); + +struct f2fs_dir_entry *find_target_dentry (struct f2fs_filename *, +f2fs_hash_t ,int *,struct f2fs_dentry_ptr *);bool f2fs_fill_dentries (struct dir_context *,struct f2fs_dentry_ptr *,unsigned int ,struct f2fs_str *); void do_make_empty_dir(struct inode *, struct inode *,
@@ -1931,8 +1932,8 @@ int f2fs_convert_inline_page(struct dnode_of_data *, struct page *);int f2fs_convert_inline_inode (struct inode *);int f2fs_write_inline_data (struct inode *,struct page *);bool recover_inline_data (struct inode *,struct page *); -struct f2fs_dir_entry *find_in_inline_dir (struct inode *,struct qstr *, -struct page **); +struct f2fs_dir_entry *find_in_inline_dir (struct inode *, +struct f2fs_filename *,struct page **);struct f2fs_dir_entry *f2fs_parent_inline_dir (struct inode *,struct page **);int make_empty_inline_dir (struct inode *inode,struct inode *,struct page *); int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,
fs/f2fs/inline.c +6 -3
@@ -284,23 +284,26 @@ process_inline: }struct f2fs_dir_entry *find_in_inline_dir (struct inode *dir, -struct qstr *name,struct page **res_page) +struct f2fs_filename *fname,struct page **res_page) {struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb);struct f2fs_inline_dentry *inline_dentry; +struct qstr name =FSTR_TO_QSTR (&fname->disk_name);struct f2fs_dir_entry *de;struct f2fs_dentry_ptr d;struct page *ipage; +f2fs_hash_t namehash; ipage =get_node_page (sbi, dir->i_ino);if (IS_ERR (ipage))return NULL ; + namehash =f2fs_dentry_hash (&name); + inline_dentry =inline_data_addr (ipage);make_dentry_ptr (NULL , &d, (void *)inline_dentry,2 ); - de =find_target_dentry (name,NULL , &d); - + de =find_target_dentry (fname, namehash,NULL , &d);unlock_page (ipage);if (de) *res_page = ipage;
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Re: [f2fs-dev] [PATCH 14/18] f2fs crypto: add filename encryption for f2fs_lookup
Hi Jaegeuk,
While compiling git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
branch dev(commit 5af6e74892a f2fs crypto: remove checking key context during lookup), I saw an error:
fs/f2fs/dir.c: In function ‘find_in_level’:fs/f2fs/dir.c:163: error: unknown field ‘len’ specified in initializer fs/f2fs/dir.c:163: warning: excess elements in struct initializer fs/f2fs/dir.c:163: warning: (near initialization for ‘name’)
I think it's related to this patch.
If there is anything wrong in my configuration, please let me know.
Thanks,
Hu
Quoted 221 lines · Jaegeuk Kim
This patch implements filename encryption support for
f2fs_lookup.Note that,
f2fs_find_entryshould be outside of f2fs_(un)lock_op().Signed-off-by Jaegeuk Kim <[email protected]>--- fs/f2fs/dir.c | 79 ++++++++++++++++++++++++++++++++------------------------ fs/f2fs/f2fs.h | 9 ++++--- fs/f2fs/inline.c | 9 ++++--- 3 files changed, 56 insertions(+), 41 deletions(-)fs/f2fs/dir.c +45
-34@@ -76,20 +76,10 @@ static unsigned long dir_block_index(unsigned int level,return bidx; } -static bool early_match_name (size_t namelen,f2fs_hash_t namehash, -struct f2fs_dir_entry *de) -{ -if (le16_to_cpu (de->name_len) != namelen) -return false; - -if (de->hash_code != namehash) -return false; - -return true; -} -static struct f2fs_dir_entry *find_in_block (struct page *dentry_page, -struct qstr *name,int *max_slots, +struct f2fs_filename *fname, +f2fs_hash_t namehash, +int *max_slots,struct page **res_page) {struct f2fs_dentry_block *dentry_blk;@@ -99,8 +89,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, dentry_blk = (struct f2fs_dentry_block *)kmap (dentry_page);make_dentry_ptr (NULL , &d, (void *)dentry_blk,1 ); - de =find_target_dentry (name, max_slots, &d); - + de =find_target_dentry (fname, namehash, max_slots, &d);if (de) *res_page = dentry_page;else @@ -114,13 +103,15 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,return de; } -struct f2fs_dir_entry *find_target_dentry (struct qstr *name,int *max_slots, -struct f2fs_dentry_ptr *d) +struct f2fs_dir_entry *find_target_dentry (struct f2fs_filename *fname, +f2fs_hash_t namehash,int *max_slots, +struct f2fs_dentry_ptr *d) {struct f2fs_dir_entry *de;unsigned long bit_pos =0 ; -f2fs_hash_t namehash =f2fs_dentry_hash (name);int max_len =0 ; +struct f2fs_str de_name =FSTR_INIT (NULL ,0 ); +struct f2fs_str *name = &fname->disk_name;if (max_slots) *max_slots =0 ;@@ -132,8 +123,18 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, } de = &d->dentry[bit_pos]; -if (early_match_name (name->len, namehash, de) && - !memcmp (d->filename[bit_pos], name->name, name->len)) + +/* encrypted case */ + de_name.name = d->filename[bit_pos]; + de_name.len =le16_to_cpu (de->name_len); + +/* show encrypted name */ +if (fname->hash) { +if (de->hash_code == fname->hash) + goto found; + }else if (de_name.len == name->len && + de->hash_code == namehash && + !memcmp (de_name.name, name->name, name->len)) goto found;if (max_slots && max_len > *max_slots)@@ -155,16 +156,21 @@ found: }static struct f2fs_dir_entry *find_in_level (struct inode *dir, -unsigned int level,struct qstr *name, -f2fs_hash_t namehash,struct page **res_page) +unsigned int level, +struct f2fs_filename *fname, +struct page **res_page) { -int s =GET_DENTRY_SLOTS (name->len); +struct qstr name =FSTR_TO_QSTR (&fname->disk_name); +int s =GET_DENTRY_SLOTS (name.len);unsigned int nbucket, nblock;unsigned int bidx, end_block;struct page *dentry_page;struct f2fs_dir_entry *de =NULL ;bool room = false;int max_slots; +f2fs_hash_t namehash; + + namehash =f2fs_dentry_hash (&name);f2fs_bug_on (F2FS_I_SB (dir), level >MAX_DIR_HASH_DEPTH );@@ -183,7 +189,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,continue ; } - de =find_in_block (dentry_page, name, &max_slots, res_page); + de =find_in_block (dentry_page, fname, namehash, &max_slots, + res_page);if (de)break ;@@ -211,30 +218,34 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, {unsigned long npages =dir_blocks (dir);struct f2fs_dir_entry *de =NULL ; -f2fs_hash_t name_hash;unsigned int max_depth;unsigned int level; +struct f2fs_filename fname; +int err; *res_page =NULL ; -if (f2fs_has_inline_dentry (dir)) -return find_in_inline_dir (dir, child, res_page); + err =f2fs_fname_setup_filename (dir, child,1 , &fname); +if (err) +return NULL ; + +if (f2fs_has_inline_dentry (dir)) { + de =find_in_inline_dir (dir, &fname, res_page); + goto out; + }if (npages ==0 ) -return NULL ; + goto out; - name_hash =f2fs_dentry_hash (child); max_depth =F2FS_I (dir)->i_current_depth;for (level =0 ; level < max_depth; level++) { - de =find_in_level (dir, level, child, name_hash, res_page); + de =find_in_level (dir, level, &fname, res_page);if (de)break ; } -if (!de &&F2FS_I (dir)->chash != name_hash) { -F2FS_I (dir)->chash = name_hash; -F2FS_I (dir)->clevel = level -1 ; - } +out: +f2fs_fname_free_filename (&fname);return de; }fs/f2fs/f2fs.h +5
-4@@ -1584,8 +1584,9 @@ struct dentry *f2fs_get_parent(struct dentry *child);*/ extern unsigned char f2fs_filetype_table[F2FS_FT_MAX ];void set_de_type (struct f2fs_dir_entry *,umode_t ); -struct f2fs_dir_entry *find_target_dentry (struct qstr *,int *, -struct f2fs_dentry_ptr *); + +struct f2fs_dir_entry *find_target_dentry (struct f2fs_filename *, +f2fs_hash_t ,int *,struct f2fs_dentry_ptr *);bool f2fs_fill_dentries (struct dir_context *,struct f2fs_dentry_ptr *,unsigned int ,struct f2fs_str *); void do_make_empty_dir(struct inode *, struct inode *,@@ -1931,8 +1932,8 @@ int f2fs_convert_inline_page(struct dnode_of_data *, struct page *);int f2fs_convert_inline_inode (struct inode *);int f2fs_write_inline_data (struct inode *,struct page *);bool recover_inline_data (struct inode *,struct page *); -struct f2fs_dir_entry *find_in_inline_dir (struct inode *,struct qstr *, -struct page **); +struct f2fs_dir_entry *find_in_inline_dir (struct inode *, +struct f2fs_filename *,struct page **);struct f2fs_dir_entry *f2fs_parent_inline_dir (struct inode *,struct page **);int make_empty_inline_dir (struct inode *inode,struct inode *,struct page *); int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,fs/f2fs/inline.c +4
-1@@ -284,23 +284,26 @@ process_inline: }struct f2fs_dir_entry *find_in_inline_dir (struct inode *dir, -struct qstr *name,struct page **res_page) +struct f2fs_filename *fname,struct page **res_page) {struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb);struct f2fs_inline_dentry *inline_dentry; +struct qstr name =FSTR_TO_QSTR (&fname->disk_name);struct f2fs_dir_entry *de;struct f2fs_dentry_ptr d;struct page *ipage; +f2fs_hash_t namehash; ipage =get_node_page (sbi, dir->i_ino);if (IS_ERR (ipage))return NULL ; + namehash =f2fs_dentry_hash (&name);
fs/f2fs/inline.c process_inline: · line 309
Quoted 10 lines
fs/f2fs/inline.c +2
-2+ inline_dentry =inline_data_addr (ipage);make_dentry_ptr (NULL , &d, (void *)inline_dentry,2 ); - de =find_target_dentry (name,NULL , &d); - + de =find_target_dentry (fname, namehash,NULL , &d);unlock_page (ipage);if (de) *res_page = ipage;
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerRe: [f2fs-dev] [PATCH 14/18] f2fs crypto: add filename encryption for f2fs_lookup
Hi Hujianynag,
I just fixed it up, and rebased the dev branch.
Could you check them out?
Thanks,
Quoted 243 lines · hujianyang
Hi Jaegeuk,
While compiling
git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
branch dev(commit5af6e74892af2fs crypto: remove checking key context during lookup), I saw an error:
fs/f2fs/dir.c: In function ‘find_in_level’:fs/f2fs/dir.c:163: error: unknown field ‘len’ specified in initializerfs/f2fs/dir.c:163: warning: excess elements in struct initializerfs/f2fs/dir.c:163: warning: (near initialization for ‘name’)I think it's related to this patch.
If there is anything wrong in my configuration, please let me know.Thanks,
HuQuoted 223 lines · Jaegeuk Kim
This patch implements filename encryption support for
f2fs_lookup.Note that,
f2fs_find_entryshould be outside of f2fs_(un)lock_op().Signed-off-by Jaegeuk Kim <[email protected]>--- fs/f2fs/dir.c | 79 ++++++++++++++++++++++++++++++++------------------------ fs/f2fs/f2fs.h | 9 ++++--- fs/f2fs/inline.c | 9 ++++--- 3 files changed, 56 insertions(+), 41 deletions(-)fs/f2fs/dir.c +45
-34@@ -76,20 +76,10 @@ static unsigned long dir_block_index(unsigned int level,return bidx; } -static bool early_match_name (size_t namelen,f2fs_hash_t namehash, -struct f2fs_dir_entry *de) -{ -if (le16_to_cpu (de->name_len) != namelen) -return false; - -if (de->hash_code != namehash) -return false; - -return true; -} -static struct f2fs_dir_entry *find_in_block (struct page *dentry_page, -struct qstr *name,int *max_slots, +struct f2fs_filename *fname, +f2fs_hash_t namehash, +int *max_slots,struct page **res_page) {struct f2fs_dentry_block *dentry_blk;@@ -99,8 +89,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, dentry_blk = (struct f2fs_dentry_block *)kmap (dentry_page);make_dentry_ptr (NULL , &d, (void *)dentry_blk,1 ); - de =find_target_dentry (name, max_slots, &d); - + de =find_target_dentry (fname, namehash, max_slots, &d);if (de) *res_page = dentry_page;else @@ -114,13 +103,15 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,return de; } -struct f2fs_dir_entry *find_target_dentry (struct qstr *name,int *max_slots, -struct f2fs_dentry_ptr *d) +struct f2fs_dir_entry *find_target_dentry (struct f2fs_filename *fname, +f2fs_hash_t namehash,int *max_slots, +struct f2fs_dentry_ptr *d) {struct f2fs_dir_entry *de;unsigned long bit_pos =0 ; -f2fs_hash_t namehash =f2fs_dentry_hash (name);int max_len =0 ; +struct f2fs_str de_name =FSTR_INIT (NULL ,0 ); +struct f2fs_str *name = &fname->disk_name;if (max_slots) *max_slots =0 ;@@ -132,8 +123,18 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, } de = &d->dentry[bit_pos]; -if (early_match_name (name->len, namehash, de) && - !memcmp (d->filename[bit_pos], name->name, name->len)) + +/* encrypted case */ + de_name.name = d->filename[bit_pos]; + de_name.len =le16_to_cpu (de->name_len); + +/* show encrypted name */ +if (fname->hash) { +if (de->hash_code == fname->hash) + goto found; + }else if (de_name.len == name->len && + de->hash_code == namehash && + !memcmp (de_name.name, name->name, name->len)) goto found;if (max_slots && max_len > *max_slots)@@ -155,16 +156,21 @@ found: }static struct f2fs_dir_entry *find_in_level (struct inode *dir, -unsigned int level,struct qstr *name, -f2fs_hash_t namehash,struct page **res_page) +unsigned int level, +struct f2fs_filename *fname, +struct page **res_page) { -int s =GET_DENTRY_SLOTS (name->len); +struct qstr name =FSTR_TO_QSTR (&fname->disk_name); +int s =GET_DENTRY_SLOTS (name.len);unsigned int nbucket, nblock;unsigned int bidx, end_block;struct page *dentry_page;struct f2fs_dir_entry *de =NULL ;bool room = false;int max_slots; +f2fs_hash_t namehash; + + namehash =f2fs_dentry_hash (&name);f2fs_bug_on (F2FS_I_SB (dir), level >MAX_DIR_HASH_DEPTH );@@ -183,7 +189,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,continue ; } - de =find_in_block (dentry_page, name, &max_slots, res_page); + de =find_in_block (dentry_page, fname, namehash, &max_slots, + res_page);if (de)break ;@@ -211,30 +218,34 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, {unsigned long npages =dir_blocks (dir);struct f2fs_dir_entry *de =NULL ; -f2fs_hash_t name_hash;unsigned int max_depth;unsigned int level; +struct f2fs_filename fname; +int err; *res_page =NULL ; -if (f2fs_has_inline_dentry (dir)) -return find_in_inline_dir (dir, child, res_page); + err =f2fs_fname_setup_filename (dir, child,1 , &fname); +if (err) +return NULL ; + +if (f2fs_has_inline_dentry (dir)) { + de =find_in_inline_dir (dir, &fname, res_page); + goto out; + }if (npages ==0 ) -return NULL ; + goto out; - name_hash =f2fs_dentry_hash (child); max_depth =F2FS_I (dir)->i_current_depth;for (level =0 ; level < max_depth; level++) { - de =find_in_level (dir, level, child, name_hash, res_page); + de =find_in_level (dir, level, &fname, res_page);if (de)break ; } -if (!de &&F2FS_I (dir)->chash != name_hash) { -F2FS_I (dir)->chash = name_hash; -F2FS_I (dir)->clevel = level -1 ; - } +out: +f2fs_fname_free_filename (&fname);return de; }fs/f2fs/f2fs.h +5
-4@@ -1584,8 +1584,9 @@ struct dentry *f2fs_get_parent(struct dentry *child);*/ extern unsigned char f2fs_filetype_table[F2FS_FT_MAX ];void set_de_type (struct f2fs_dir_entry *,umode_t ); -struct f2fs_dir_entry *find_target_dentry (struct qstr *,int *, -struct f2fs_dentry_ptr *); + +struct f2fs_dir_entry *find_target_dentry (struct f2fs_filename *, +f2fs_hash_t ,int *,struct f2fs_dentry_ptr *);bool f2fs_fill_dentries (struct dir_context *,struct f2fs_dentry_ptr *,unsigned int ,struct f2fs_str *); void do_make_empty_dir(struct inode *, struct inode *,@@ -1931,8 +1932,8 @@ int f2fs_convert_inline_page(struct dnode_of_data *, struct page *);int f2fs_convert_inline_inode (struct inode *);int f2fs_write_inline_data (struct inode *,struct page *);bool recover_inline_data (struct inode *,struct page *); -struct f2fs_dir_entry *find_in_inline_dir (struct inode *,struct qstr *, -struct page **); +struct f2fs_dir_entry *find_in_inline_dir (struct inode *, +struct f2fs_filename *,struct page **);struct f2fs_dir_entry *f2fs_parent_inline_dir (struct inode *,struct page **);int make_empty_inline_dir (struct inode *inode,struct inode *,struct page *); int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,fs/f2fs/inline.c +5
-1@@ -284,23 +284,26 @@ process_inline: }struct f2fs_dir_entry *find_in_inline_dir (struct inode *dir, -struct qstr *name,struct page **res_page) +struct f2fs_filename *fname,struct page **res_page) {struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb);struct f2fs_inline_dentry *inline_dentry; +struct qstr name =FSTR_TO_QSTR (&fname->disk_name);struct f2fs_dir_entry *de;struct f2fs_dentry_ptr d;struct page *ipage; +f2fs_hash_t namehash; ipage =get_node_page (sbi, dir->i_ino);if (IS_ERR (ipage))return NULL ; + namehash =f2fs_dentry_hash (&name); + inline_dentry =inline_data_addr (ipage);
Quoted 8 lines
fs/f2fs/inline.c process_inline: · line 309
Quoted 8 lines
fs/f2fs/inline.c +1
-2make_dentry_ptr (NULL , &d, (void *)inline_dentry,2 ); - de =find_target_dentry (name,NULL , &d); - + de =find_target_dentry (fname, namehash,NULL , &d);unlock_page (ipage);if (de) *res_page = ipage;
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [f2fs-dev] [PATCH 14/18] f2fs crypto: add filename encryption for f2fs_lookup
It's OK now.
Thanks,
Hu
Quoted 25 lines · Jaegeuk Kim
Hi Hujianynag,
I just fixed it up, and rebased the dev branch.
Could you check them out?Thanks,
Quoted 17 lines · hujianyang
Hi Jaegeuk,
While compiling
git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
branch dev(commit5af6e74892af2fs crypto: remove checking key context during lookup), I saw an error:
fs/f2fs/dir.c: In function ‘find_in_level’:fs/f2fs/dir.c:163: error: unknown field ‘len’ specified in initializerfs/f2fs/dir.c:163: warning: excess elements in struct initializerfs/f2fs/dir.c:163: warning: (near initialization for ‘name’)I think it's related to this patch.
If there is anything wrong in my configuration, please let me know.Thanks,
Hu
Jaegeuk Kim
maintainerPATCH 15/18 f2fs crypto: add filename encryption for roll-forward recovery
In reply to Jaegeuk KimThis patch adds a bit flag to indicate whether or not i_name in the inode is encrypted.
If this name is encrypted, we can't do recover_dentry during roll-forward. So, f2fs_sync_file() needs to do checkpoint, if this will be needed in future.
--- fs/f2fs/dir.c | 8 +++++++- fs/f2fs/f2fs.h | 5 ++++- fs/f2fs/file.c | 4 +++- fs/f2fs/namei.c | 20 +++++++++++++++----- fs/f2fs/recovery.c | 13 ++++++++++++- 5 files changed, 41 insertions(+), 9 deletions(-)
fs/f2fs/dir.c +7 -1
@@ -314,10 +314,14 @@ static void init_dent_inode(const struct qstr *name, struct page *ipage)set_page_dirty (ipage); } -int update_dent_inode (struct inode *inode,const struct qstr *name) +int update_dent_inode (struct inode *inode,struct inode *to, +const struct qstr *name) {struct page *page; +if (file_enc_name (to)) +return 0 ; + page =get_node_page (F2FS_I_SB (inode), inode->i_ino);if (IS_ERR (page))return PTR_ERR (page);
@@ -597,6 +601,8 @@ add_dentry: err =PTR_ERR (page); goto fail; } +if (f2fs_encrypted_inode (dir)) +file_set_enc_name (inode); }make_dentry_ptr (NULL , &d, (void *)dentry_blk,1 );
fs/f2fs/f2fs.h +4 -1
@@ -378,6 +378,7 @@ struct f2fs_map_blocks {#define FADVISE_COLD_BIT 0x01#define FADVISE_LOST_PINO_BIT 0x02#define FADVISE_ENCRYPT_BIT 0x04 +#define FADVISE_ENC_NAME_BIT 0x08#define file_is_cold (inode) is_file(inode, FADVISE_COLD_BIT)#define file_wrong_pino (inode) is_file(inode, FADVISE_LOST_PINO_BIT)
@@ -388,6 +389,8 @@ struct f2fs_map_blocks {#define file_is_encrypt (inode) is_file(inode, FADVISE_ENCRYPT_BIT)#define file_set_encrypt (inode) set_file(inode, FADVISE_ENCRYPT_BIT)#define file_clear_encrypt (inode) clear_file(inode, FADVISE_ENCRYPT_BIT) +#define file_enc_name (inode) is_file(inode, FADVISE_ENC_NAME_BIT) +#define file_set_enc_name (inode) set_file(inode, FADVISE_ENC_NAME_BIT)/* Encryption algorithms */ #define F2FS_ENCRYPTION_MODE_INVALID 0
@@ -1602,7 +1605,7 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);ino_t f2fs_inode_by_name (struct inode *,struct qstr *);void f2fs_set_link (struct inode *,struct f2fs_dir_entry *,struct page *,struct inode *); -int update_dent_inode (struct inode *,const struct qstr *); +int update_dent_inode (struct inode *,struct inode *,const struct qstr *);void f2fs_update_dentry (nid_t ino,umode_t mode,struct f2fs_dentry_ptr *,const struct qstr *,f2fs_hash_t ,unsigned int ); int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *, nid_t,
fs/f2fs/file.c +3 -1
@@ -106,7 +106,7 @@ static int get_parent_ino(struct inode *inode, nid_t *pino)if (!dentry)return 0 ; -if (update_dent_inode (inode, &dentry->d_name)) { +if (update_dent_inode (inode, inode, &dentry->d_name)) {dput (dentry);return 0 ; }
@@ -123,6 +123,8 @@ static inline bool need_do_checkpoint(struct inode *inode)if (!S_ISREG (inode->i_mode) || inode->i_nlink !=1 ) need_cp = true; +else if (file_enc_name (inode) &&need_dentry_mark (sbi, inode->i_ino)) + need_cp = true;else if (file_wrong_pino (inode)) need_cp = true;else if (!space_for_roll_forward (sbi))
fs/f2fs/namei.c +15 -5
@@ -517,7 +517,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,if (err) goto put_out_dir; -if (update_dent_inode (old_inode, &new_dentry->d_name)) { +if (update_dent_inode (old_inode, new_inode, + &new_dentry->d_name)) {release_orphan_inode (sbi); goto put_out_dir; }
@@ -557,6 +558,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,down_write (&F2FS_I (old_inode)->i_sem);file_lost_pino (old_inode); +if (new_inode &&file_enc_name (new_inode)) +file_set_enc_name (old_inode);up_write (&F2FS_I (old_inode)->i_sem); old_inode->i_ctime =CURRENT_TIME ;
@@ -659,13 +662,17 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,f2fs_lock_op (sbi); - err =update_dent_inode (old_inode, &new_dentry->d_name); + err =update_dent_inode (old_inode, new_inode, &new_dentry->d_name);if (err) goto out_unlock; +if (file_enc_name (new_inode)) +file_set_enc_name (old_inode); - err =update_dent_inode (new_inode, &old_dentry->d_name); + err =update_dent_inode (new_inode, old_inode, &old_dentry->d_name);if (err) goto out_undo; +if (file_enc_name (old_inode)) +file_set_enc_name (new_inode);/* update ".." directory entry info of old dentry */ if (old_dir_entry)
@@ -723,8 +730,11 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,f2fs_sync_fs (sbi->sb,1 );return 0 ; out_undo: -/* Still we may fail to recover name info of f2fs_inode here */ -update_dent_inode (old_inode, &old_dentry->d_name); +/* +* Still we may fail to recover name info of f2fs_inode here +* Drop it, once its name is set as encrypted +*/ +update_dent_inode (old_inode, old_inode, &old_dentry->d_name); out_unlock:f2fs_unlock_op (sbi); out_new_dir:
fs/f2fs/recovery.c +12 -1
@@ -83,6 +83,11 @@ static int recover_dentry(struct inode *inode, struct page *ipage) goto out; } +if (file_enc_name (inode)) { +iput (dir); +return 0 ; + } + name.len =le32_to_cpu (raw_inode->i_namelen); name.name = raw_inode->i_name;
@@ -143,6 +148,7 @@ out:static void recover_inode (struct inode *inode,struct page *page) {struct f2fs_inode *raw =F2FS_INODE (page); +char *name; inode->i_mode =le16_to_cpu (raw->i_mode);i_size_write (inode,le64_to_cpu (raw->i_size));
@@ -153,8 +159,13 @@ static void recover_inode(struct inode *inode, struct page *page) inode->i_ctime.tv_nsec =le32_to_cpu (raw->i_ctime_nsec); inode->i_mtime.tv_nsec =le32_to_cpu (raw->i_mtime_nsec); +if (file_enc_name (inode)) + name ="<encrypted>" ; +else + name =F2FS_INODE (page)->i_name; +f2fs_msg (inode->i_sb,KERN_NOTICE ,"recover_inode: ino = %x, name = %s" , -ino_of_node (page),F2FS_INODE (page)->i_name); +ino_of_node (page), name); }static int find_fsync_dnodes (struct f2fs_sb_info *sbi,struct list_head *head)
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Jaegeuk Kim
maintainerPATCH 16/18 f2fs crypto: add symlink encryption
In reply to Jaegeuk KimThis patch implements encryption support for symlink.
The codes refered the ext4 symlink path.
--- fs/f2fs/f2fs_crypto.h | 2 - fs/f2fs/namei.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 135 insertions(+), 5 deletions(-)
fs/f2fs/f2fs_crypto.h +0 -2
@@ -145,8 +145,6 @@ struct f2fs_encrypted_symlink_data {*/ static inline u32 encrypted_symlink_data_len (u32 l) { -if (l <F2FS_CRYPTO_BLOCK_SIZE ) - l =F2FS_CRYPTO_BLOCK_SIZE ;return (l +sizeof (struct f2fs_encrypted_symlink_data ) -1 ); }#endif /* _F2FS_CRYPTO_H */
fs/f2fs/namei.c +135 -3
174 lines not on this page · raw message
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
Re: [PATCH 16/18] f2fs crypto: add symlink encryption
Quoted 3 lines · Jaegeuk Kim
This patch implements encryption support for symlink.
The codes refered the ext4 symlink path.
ext4 symlink patches are seriously misguided - don't mix encrypted and unencrypted cases in the same inode_operations.
NAK.
Jaegeuk Kim
maintainerRe: [PATCH 16/18] f2fs crypto: add symlink encryption
Quoted 7 lines · Al Viro
Quoted 3 lines · Jaegeuk Kim
This patch implements encryption support for symlink.
The codes refered the ext4 symlink path.
ext4 symlink patches are seriously misguided - don't mix encrypted and unencrypted cases in the same
inode_operations.
Ok. Let me split them into separated inode_operations.
Thanks,
Quoted 2 lines
NAK.
Jaegeuk Kim
maintainerRe: [PATCH 16/18 v2] f2fs crypto: add symlink encryption
In reply to Jaegeuk KimChage log from v1:
o split inode_operations suggested by Al
This patch implements encryption support for symlink.
--- fs/f2fs/f2fs.h | 1 + fs/f2fs/inode.c | 5 +- fs/f2fs/namei.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 145 insertions(+), 6 deletions(-)
fs/f2fs/f2fs.h +1 -0
@@ -1920,6 +1920,7 @@ extern const struct address_space_operations f2fs_node_aops;extern const struct address_space_operations f2fs_meta_aops;extern const struct inode_operations f2fs_dir_inode_operations;extern const struct inode_operations f2fs_symlink_inode_operations; +extern const struct inode_operations f2fs_encrypted_symlink_inode_operations;extern const struct inode_operations f2fs_special_inode_operations;extern struct kmem_cache *inode_entry_slab;
fs/f2fs/inode.c +4 -1
@@ -198,7 +198,10 @@ make_now: inode->i_mapping->a_ops = &f2fs_dblock_aops;mapping_set_gfp_mask (inode->i_mapping,GFP_F2FS_HIGH_ZERO ); }else if (S_ISLNK (inode->i_mode)) { - inode->i_op = &f2fs_symlink_inode_operations; +if (f2fs_encrypted_inode (inode)) + inode->i_op = &f2fs_encrypted_symlink_inode_operations; +else + inode->i_op = &f2fs_symlink_inode_operations; inode->i_mapping->a_ops = &f2fs_dblock_aops; }else if (S_ISCHR (inode->i_mode) ||S_ISBLK (inode->i_mode) ||S_ISFIFO (inode->i_mode) ||S_ISSOCK (inode->i_mode)) {
fs/f2fs/namei.c +140 -5
182 lines not on this page · raw message
Signature · 1 line
2.1.1
Jaegeuk Kim
maintainerPATCH 17/18 f2fs crypto: fix missing key when reading a page
In reply to Jaegeuk Kim1. mount $mnt
2. cp data $mnt/
3. umount $mnt
4. log out
5. log in
6. cat $mnt/data
-> panic, due to no i_crypt_info.
--- fs/f2fs/crypto.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/f2fs/crypto.c +3 -1
@@ -131,7 +131,9 @@ struct f2fs_crypto_ctx *f2fs_get_crypto_ctx(struct inode *inode)unsigned long flags;struct f2fs_crypt_info *ci =F2FS_I (inode)->i_crypt_info; -BUG_ON (ci ==NULL ); +if (ci ==NULL ) +return ERR_PTR (-EACCES ); +/* * We first try getting the ctx from a free list because in * the common case the ctx will have an allocated and
Signature · 1 line
2.1.1
Jaegeuk Kim
maintainerPATCH 18/18 f2fs crypto: remove checking key context during lookup
In reply to Jaegeuk KimNo matter what the key is valid or not, readdir shows the dir entries correctly. So, lookup should not failed.
But, we expect further accesses should be denied from open, rename, link, and so on.
--- fs/f2fs/namei.c | 10 ---------- 1 file changed, 10 deletions(-)
fs/f2fs/namei.c +0 -10
@@ -260,16 +260,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,if (IS_ERR (inode))return ERR_CAST (inode); -if (f2fs_encrypted_inode (dir) &&f2fs_may_encrypt (inode) && - !f2fs_is_child_context_consistent_with_parent (dir, inode)) { -iput (inode); -f2fs_msg (inode->i_sb,KERN_WARNING , -"Inconsistent encryption contexts: %lu/%lu\n" , - (unsigned long )dir->i_ino, - (unsigned long )inode->i_ino); -return ERR_PTR (-EPERM ); - } -if (f2fs_has_inline_dots (inode)) { err =__recover_dot_dentries (inode, dir->i_ino);if (err)
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y