All of lore.kernel.org
 help / color / mirror / Atom feed
From: Allison Henderson <achender@linux.vnet.ibm.com>
To: djwong@us.ibm.com
Cc: linux-ext4@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: [Ext4 Secure Delete 3/7v4] ext4: Secure Delete: Add secure	delete functions
Date: Fri, 07 Oct 2011 16:08:14 -0700	[thread overview]
Message-ID: <4E8F865E.9070909@linux.vnet.ibm.com> (raw)
In-Reply-To: <20111007180711.GH12447@tux1.beaverton.ibm.com>

On 10/07/2011 11:07 AM, Darrick J. Wong wrote:
> On Fri, Oct 07, 2011 at 12:11:01AM -0700, Allison Henderson wrote:
>> This patch adds two new routines: ext4_secure_delete_pblks
>> and ext4_secure_delete_lblks.
>>
>> ext4_secure_delete_pblks() will write zeros to the specified
>> physical blocks or random data if the EXT4_SECRM_RANDOM_FL flag is
>> set.  If the device supports secure discard, the secure
>> discard will be used instead. ext4_secure_delete_lblks handels walking
>
> handles
>
>> the logical blocks of a file and calling ext4_secure_delete_pblks()
>> as needed.
>>
>> Signed-off-by: Allison Henderson<achender@linux.vnet.ibm.com>
>> ---
>> v1->v2
>> Removed check for discard mount option and replaced with
>> check for secure discard and discard_zeroes_data
>>
>> Added BLKDEV_DISCARD_SECURE to the sb_issue_discard call
>>
>> v2->v3
>> Removed code for discard.  A seperate patch will
>
> separate
>
>> be done to add that code in the block layer
>>
>> v3->v4
>> Discard code will be kept in the vfs layer.  Code
>> for secure delete is now in its own function,
>> ext4_secure_delete_pblks and is called
>> by a new function ext4_secure_delete_lblks
>> before any blocks are released
>>
>> :100644 100644 5c9f88c... 34f82a1... M	fs/ext4/ext4.h
>> :100644 100644 095c36f... 10180e3... M	fs/ext4/ext4_extents.h
>> :100644 100644 57cf568... 40d4e50... M	fs/ext4/extents.c
>> :100644 100644 9dc8c14... 0a526c4... M	fs/ext4/inode.c
>>   fs/ext4/ext4.h         |    5 +
>>   fs/ext4/ext4_extents.h |    2 +
>>   fs/ext4/extents.c      |    2 +-
>>   fs/ext4/inode.c        |  196 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   4 files changed, 204 insertions(+), 1 deletions(-)
>>
>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
>> index 5c9f88c..34f82a1 100644
>> --- a/fs/ext4/ext4.h
>> +++ b/fs/ext4/ext4.h
>> @@ -2220,6 +2220,11 @@ extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
>>   			   struct ext4_map_blocks *map, int flags);
>>   extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
>>   			__u64 start, __u64 len);
>> +extern int ext4_secure_delete_lblks(struct inode *inode,
>> +			ext4_lblk_t first_block, unsigned long count);
>> +extern int ext4_secure_delete_pblks(struct inode *inode,
>> +			ext4_fsblk_t block, unsigned long count);
>> +
>>   /* move_extent.c */
>>   extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
>>   			     __u64 start_orig, __u64 start_donor,
>> diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
>> index 095c36f..10180e3 100644
>> --- a/fs/ext4/ext4_extents.h
>> +++ b/fs/ext4/ext4_extents.h
>> @@ -290,5 +290,7 @@ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
>>   							struct ext4_ext_path *);
>>   extern void ext4_ext_drop_refs(struct ext4_ext_path *);
>>   extern int ext4_ext_check_inode(struct inode *inode);
>> +extern int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block,
>> +		struct ext4_ext_cache *ex);
>>   #endif /* _EXT4_EXTENTS */
>>
>> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
>> index 57cf568..40d4e50 100644
>> --- a/fs/ext4/extents.c
>> +++ b/fs/ext4/extents.c
>> @@ -2034,7 +2034,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
>>    *
>>    * Return 0 if cache is invalid; 1 if the cache is valid
>>    */
>> -static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block,
>> +int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block,
>>   	struct ext4_ext_cache *ex){
>>   	struct ext4_ext_cache *cex;
>>   	struct ext4_sb_info *sbi;
>> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
>> index 9dc8c14..0a526c4 100644
>> --- a/fs/ext4/inode.c
>> +++ b/fs/ext4/inode.c
>> @@ -38,6 +38,7 @@
>>   #include<linux/printk.h>
>>   #include<linux/slab.h>
>>   #include<linux/ratelimit.h>
>> +#include<linux/random.h>
>>
>>   #include "ext4_jbd2.h"
>>   #include "xattr.h"
>> @@ -713,6 +714,201 @@ static int ext4_ind_hole_lookup(struct inode *inode, ext4_lblk_t block)
>>   	return 0;
>>   }
>>
>> +
>> +/*
>> + * ext4_secure_delete_pblks
>> + *
>> + * Securely delete physical blocks.
>> + * If the devices supports secure discard,
>> + * blocks will be discarded.  Otherwise
>> + * the blocks will be either zeroed or
>> + * randomized if the random secure delete
>> + * flag is on
>
> The fact that random secure delete produces zeroed blocks on discard devices is
> documented somewhere user-visible, right?  Just in case someone actually
> depends on the randomizing.

At the moment no, the code is just the result of reviews and 
brainstorming, but I can add in some documentation somewhere so that it 
is more clear.  Will catch the misspellings too, thx!  :)

>
>> + * inode: The files inode
>> + * block: The physical block at which to start deleteing
>
> deleting
>
>> + * count: The number of blocks to delete
>> + *
>> + * Returns 0 on sucess or negative on error
>> + */
>> +int ext4_secure_delete_pblks(struct inode *inode, ext4_fsblk_t block,
>> +		unsigned long count){
>> +
>> +	struct fstrim_range range;
>> +	ext4_fsblk_t iblock, last_block;
>> +	struct buffer_head *bh;
>> +	struct super_block *sb = inode->i_sb;
>> +	struct request_queue *q = bdev_get_queue(sb->s_bdev);
>> +	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
>> +	int err = 0;
>> +
>> +	last_block = block + count;
>> +	/*
>> +	 * Check to see if the device supports secure discard,
>> +	 * And also that read after discard returns zeros
>> +	 */
>> +	if (blk_queue_secdiscard(q)&&  q->limits.discard_zeroes_data) {
>> +		err = sb_issue_discard(sb, block, count,
>> +			GFP_NOFS, BLKDEV_DISCARD_SECURE);
>> +		if (err)
>> +			goto zero_out;
>> +
>> +		range.start = block;
>> +		range.len = count;
>> +		range.minlen = 1;
>> +		err = ext4_trim_fs(sb,&range);
>> +
>> +		if (err)
>> +			goto zero_out;
>> +
>> +		return 0;
>> +	}
>> +
>> +	if (EXT4_I(inode)->i_flags&  EXT4_SECRM_RANDOM_FL) {
>> +		for (iblock = block; iblock<  last_block; iblock++) {
>> +			bh = sb_getblk(sb, iblock);
>> +			get_random_bytes(bh->b_data, bh->b_size);
>> +			set_buffer_dirty(bh);
>> +
>> +			sync_dirty_buffer(bh);
>> +			if (buffer_req(bh)&&  !buffer_uptodate(bh)) {
>> +				es->s_last_error_block =
>> +					cpu_to_le64(bh->b_blocknr);
>> +				ext4_error_inode(inode, __func__,
>> +					__LINE__, bh->b_blocknr,
>> +					"IO error syncing itable block");
>
> itable block?
>
>> +				err = -EIO;
>> +				brelse(bh);
>> +				goto zero_out;
>> +			}
>> +			brelse(bh);
>> +		}
>> +		return 0;
>> +	}
>> +
>> +zero_out:
>> +	return sb_issue_zeroout(sb, block, count, GFP_NOFS);
>> +
>> +}
>> +
>> +/*
>> + * ext4_secure_delete_lblks
>> + *
>> + * Secure deletes the data blocks of a file
>> + * starting at the given logical block
>> + *
>> + * @inode: The files inode
>> + * @first_block: Starting logical block
>> + * @count: The number of blocks to secure delete
>> + *
>> + * Returns 0 on sucess or negative on error
>> + */
>> +int ext4_secure_delete_lblks(struct inode *inode, ext4_lblk_t first_block,
>> +				unsigned long count){
>> +	handle_t *handle;
>> +	struct ext4_map_blocks map;
>> +	struct ext4_ext_cache cache_ex;
>> +	ext4_lblk_t num_blocks, max_blocks = 0;
>> +	ext4_lblk_t last_block = first_block + count;
>> +	ext4_lblk_t iblock = first_block;
>> +	int ret, credits, hole_len, err = 0;
>> +
>> +	credits = ext4_writepage_trans_blocks(inode);
>> +	handle = ext4_journal_start(inode, credits);
>> +	if (IS_ERR(handle))
>> +		return PTR_ERR(handle);
>> +
>> +	down_write(&EXT4_I(inode)->i_data_sem);
>> +	ext4_ext_invalidate_cache(inode);
>> +	ext4_discard_preallocations(inode);
>> +
>> +	/* Do not allow last_block to wrap when caller passes EXT_MAX_BLOCK */
>> +	if (last_block<  first_block)
>> +		last_block = EXT_MAX_BLOCKS;
>> +
>> +	while (iblock<  last_block) {
>> +		max_blocks = last_block - iblock;
>> +		num_blocks = 1;
>> +		memset(&map, 0, sizeof(map));
>> +		map.m_lblk = iblock;
>> +		map.m_len = max_blocks;
>> +
>> +		if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
>> +			ret = ext4_ext_map_blocks(handle, inode,&map, 0);
>> +		else
>> +			ret = ext4_ind_map_blocks(handle, inode,&map, 0);
>> +
>> +		if (ret>  0) {
>> +			err = ext4_secure_delete_pblks(inode,
>> +				map.m_pblk, map.m_len);
>> +			if (err)
>> +				break;
>> +			num_blocks = ret;
>> +		} else if (ret == 0) {
>> +			if (ext4_test_inode_flag(inode,
>> +				EXT4_INODE_EXTENTS)) {
>> +				/*
>> +				 * If map blocks could not find the block,
>> +				 * then it is in a hole.  If the hole was
>> +				 * not already cached, then map blocks should
>> +				 * put it in the cache.  So we can get the hole
>> +				 * out of the cache
>> +				 */
>> +				memset(&cache_ex, 0, sizeof(cache_ex));
>> +				if ((ext4_ext_check_cache(inode, iblock,
>> +					&cache_ex))&&  !cache_ex.ec_start) {
>> +
>> +					/* The hole is cached */
>> +					num_blocks = cache_ex.ec_block +
>> +						cache_ex.ec_len - iblock;
>> +
>> +				} else {
>> +					/* reached EOF of extent file */
>> +					break;
>> +				}
>> +			} else {
>> +				hole_len = ext4_ind_hole_lookup(inode, iblock);
>> +
>> +				if (hole_len>  0) {
>> +					/* Skip over the hole */
>> +					num_blocks = hole_len;
>> +				} else if (hole_len == 0) {
>> +					/* No hole, EOF reached */
>> +					break;
>> +				} else {
>> +					/* Hole look up err */
>> +					err = hole_len;
>> +					break;
>> +				}
>> +			}
>> +		} else {
>> +			/* Map blocks error */
>> +			err = ret;
>> +			break;
>> +		}
>> +
>> +		if (num_blocks == 0) {
>> +			/* This condition should never happen */
>> +			ext_debug("Block lookup failed");
>> +			err = -EIO;
>> +			break;
>> +		}
>> +
>> +		iblock += num_blocks;
>> +	}
>> +
>> +	if (IS_SYNC(inode))
>> +		ext4_handle_sync(handle);
>> +
>> +	up_write(&EXT4_I(inode)->i_data_sem);
>> +
>> +	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
>> +	ext4_mark_inode_dirty(handle, inode);
>> +	ext4_journal_stop(handle);
>> +
>> +	return err;
>> +}
>> +
>>   struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
>>   			       ext4_lblk_t block, int create, int *err)
>>   {
>> --
>> 1.7.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>


  reply	other threads:[~2011-10-07 23:09 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-07  7:10 [Ext4 Secure Delete 0/7 v4] Ext4 secure delete Allison Henderson
2011-10-07  7:10 ` [Ext4 Secure Delete 1/7v4] ext4: Secure Delete: Add new EXT4_SECRM_RANDOM_FL flag Allison Henderson
2011-10-07 17:02   ` Darrick J. Wong
2011-10-07 17:14     ` Allison Henderson
2011-10-07  7:11 ` [Ext4 Secure Delete 2/7v4] ext4: Secure Delete: Add ext4_ind_hole_lookup function Allison Henderson
2011-10-07 17:47   ` Darrick J. Wong
2011-10-07 23:10     ` Allison Henderson
2011-10-07  7:11 ` [Ext4 Secure Delete 3/7v4] ext4: Secure Delete: Add secure delete functions Allison Henderson
2011-10-07 17:19   ` Allison Henderson
2011-10-07 18:07   ` Darrick J. Wong
2011-10-07 23:08     ` Allison Henderson [this message]
2011-10-07  7:11 ` [Ext4 Secure Delete 4/7v4] ext4: Secure Delete: Secure delete file data Allison Henderson
2011-10-07  7:11 ` [Ext4 Secure Delete 5/7v4] ext4: Secure Delete: Secure delete directory entry Allison Henderson
2011-10-07 17:22   ` Darrick J. Wong
2011-10-07 17:59     ` Allison Henderson
2011-10-07  7:11 ` [Ext4 Secure Delete 6/7v4] ext4: Secure Delete: Secure delete meta data blocks Allison Henderson
2011-10-07  7:11 ` [Ext4 Secure Delete 7/7v4] ext4/jbd2: Secure Delete: Secure delete journal blocks Allison Henderson
2011-10-07 18:35   ` Darrick J. Wong
2011-10-07 19:31     ` Sunil Mushran
2011-10-07 19:54     ` Eric Sandeen
2011-10-07 20:14       ` Allison Henderson
2011-10-07 19:55     ` Allison Henderson
2011-10-07 20:58       ` Darrick J. Wong
2011-10-08  0:06         ` Allison Henderson
2011-10-10 19:47   ` Jonathan Corbet
2011-10-10 23:35     ` Allison Henderson
2011-10-10 23:41       ` Jonathan Corbet
2011-10-11  0:54         ` Allison Henderson
2011-10-10 20:00   ` Jonathan Corbet
2011-10-10 23:36     ` Allison Henderson
2011-10-07 15:21 ` [Ext4 Secure Delete 0/7 v4] Ext4 secure delete Andreas Dilger
2011-10-07 17:07   ` Allison Henderson
2011-10-10 17:20     ` Allison Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4E8F865E.9070909@linux.vnet.ibm.com \
    --to=achender@linux.vnet.ibm.com \
    --cc=djwong@us.ibm.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.