All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitriy Monakhov <dmonakhov@sw.ru>
To: Dmitriy Monakhov <dmonakhov@openvz.org>
Cc: Linux Kernel <linux-kernel@vger.kernel.org>,
	ecryptfs-devel@lists.sourceforge.net
Subject: Re: [PATCH] ecryptfs lower file handling code issues
Date: Mon, 12 Feb 2007 21:24:19 +0300	[thread overview]
Message-ID: <87bqjzcjzg.fsf@sw.ru> (raw)
In-Reply-To: <87d54loqsb.fsf@sw.ru> (Dmitriy Monakhov's message of "Wed, 07 Feb 2007 19:50:44 +0300")

Dmitriy Monakhov <dmonakhov@openvz.org> writes:

> eCryptfs lower file handling code has several issues:
>   - Retval from prepare_write()/commit_writ() was't checked to equality 
>     to AOP_TRUNCATED_PAGE.
>   - In some places page was't unmapped and unlocked after error.
it is easy to retproduce:
##Prepare FS
dd if=/dev/zero of=FS.img bs=1M count=64
mkfs.ext3 -F FS.img 
mkdir crypt_root
mkdir crypt_private
mount FS.img crypt_private/ -oloop
mount -t ecryptfs crypt_private/ crypt_root/ -ocipher=aes
## exhaust all available space, and provoke ENOSPC condition.
for ((i=0;i<100;i++));do dd if=/dev/zero of=crypt_root/file$i bs=1M count=1;done
###### after  this we got folowing errors on console:
#process_new_file: Error preparing to write header page out; rc = [-28]
#ecryptfs_commit_write: Error processing new file; rc = [-28]
#write_zeros: Error attempting to write zero's to remainder of page at index [0x0000000000000000]
#ecryptfs_fill_zeros: write_zeros(file=[f561bde0], index=[0x0000000000000000], old_end_pos_in_page=[d], (PAGE_CACHE_SIZE - new_end_pos_in_page=[-1])=[d]) returned [0]
#grow_file: Error attempting to fill zeros in file; rc = [-28]

# After prepare_write() failed in process_new_file() page was't unlocked,
# so leter umount will stuck forever in D state. 
umount crypt_root/
umount crypt_private/ ## stuck forever here.
>
> Signed-off-by: Dmitriy Monakhov <dmonakhov@openvz.org>
> --------------   
> diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
> index 06843d2..27ac9ef 100644
> --- a/fs/ecryptfs/mmap.c
> +++ b/fs/ecryptfs/mmap.c
> @@ -391,12 +391,14 @@ out:
>  	return rc;
>  }
>  
> -static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
> +static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page,
> +		int page_locked)
>  {
>  	kunmap(lower_page);
>  	ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = "
>  			"[0x%.16x]\n", lower_page->index);
> -	unlock_page(lower_page);
> +	if (page_locked)
> +		unlock_page(lower_page);
>  	page_cache_release(lower_page);
>  }
>  
> @@ -417,6 +419,7 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file,
>  	char *header_virt;
>  	const struct address_space_operations *lower_a_ops;
>  	u64 file_size;
> +	int pg_locked = 1;
>  
>  	rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt,
>  					      lower_inode, 0);
> @@ -427,6 +430,12 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file,
>  	}
>  	lower_a_ops = lower_inode->i_mapping->a_ops;
>  	rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8);
> +	if (rc) {
> +		if (rc == AOP_TRUNCATED_PAGE)
> +			pg_locked = 0;
> +		ecryptfs_unmap_and_release_lower_page(header_page, pg_locked);
> +		goto out;
> +	}
>  	file_size = (u64)i_size_read(inode);
>  	ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
>  	file_size = cpu_to_be64(file_size);
> @@ -435,7 +444,9 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file,
>  	if (rc < 0)
>  		ecryptfs_printk(KERN_ERR, "Error commiting header page "
>  				"write\n");
> -	ecryptfs_unmap_and_release_lower_page(header_page);
> +	if (rc == AOP_TRUNCATED_PAGE)
> +		pg_locked = 0;
> +	ecryptfs_unmap_and_release_lower_page(header_page, pg_locked);
>  	lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
>  	mark_inode_dirty_sync(inode);
>  out:
> @@ -468,7 +479,10 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
>  	}
>  out:
>  	if (rc && (*lower_page)) {
> -		ecryptfs_unmap_and_release_lower_page(*lower_page);
> +		int pg_locked = 1;
> +		if (rc == AOP_TRUNCATED_PAGE)
> +			pg_locked = 0;
> +		ecryptfs_unmap_and_release_lower_page(*lower_page, pg_locked);
>  		(*lower_page) = NULL;
>  	}
>  	return rc;
> @@ -484,16 +498,19 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
>  			   struct file *lower_file, int byte_offset,
>  			   int region_size)
>  {
> +	int pg_locked = 1;
>  	int rc = 0;
>  
>  	rc = lower_inode->i_mapping->a_ops->commit_write(
>  		lower_file, lower_page, byte_offset, region_size);
> +	if (rc == AOP_TRUNCATED_PAGE)
> +		pg_locked = 0;
>  	if (rc < 0) {
>  		ecryptfs_printk(KERN_ERR,
>  				"Error committing write; rc = [%d]\n", rc);
>  	} else
>  		rc = 0;
> -	ecryptfs_unmap_and_release_lower_page(lower_page);
> +	ecryptfs_unmap_and_release_lower_page(lower_page, pg_locked);
>  	return rc;
>  }
>  
> @@ -541,6 +558,7 @@ process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
>  	int current_header_page = 0;
>  	int header_pages;
>  	int more_header_data_to_be_written = 1;
> +	int pg_locked = 1;
>  
>  	lower_inode = ecryptfs_inode_to_lower(inode);
>  	lower_file = ecryptfs_file_to_lower(file);
> @@ -563,6 +581,10 @@ process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
>  		rc = lower_a_ops->prepare_write(lower_file, header_page, 0,
>  						PAGE_CACHE_SIZE);
>  		if (rc) {
> +			if (rc == AOP_TRUNCATED_PAGE)
> +				pg_locked = 0;
> +			ecryptfs_unmap_and_release_lower_page(header_page,
> +				pg_locked);
>  			ecryptfs_printk(KERN_ERR, "Error preparing to write "
>  					"header page out; rc = [%d]\n", rc);
>  			goto out;
> @@ -579,7 +601,7 @@ process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
>  				rc = -EIO;
>  				memset(header_virt, 0, PAGE_CACHE_SIZE);
>  				ecryptfs_unmap_and_release_lower_page(
> -					header_page);
> +					header_page, pg_locked);
>  				goto out;
>  			}
>  			if (current_header_page == 0)
> @@ -588,7 +610,9 @@ process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
>  		}
>  		rc = lower_a_ops->commit_write(lower_file, header_page, 0,
>  					       PAGE_CACHE_SIZE);
> -		ecryptfs_unmap_and_release_lower_page(header_page);
> +		if (rc == AOP_TRUNCATED_PAGE)
> +			pg_locked = 0;
> +		ecryptfs_unmap_and_release_lower_page(header_page, pg_locked);
>  		if (rc < 0) {
>  			ecryptfs_printk(KERN_ERR,
>  					"Error commiting header page write; "


  reply	other threads:[~2007-02-12 18:25 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-02-07 16:50 [PATCH] ecryptfs lower file handling code issues Dmitriy Monakhov
2007-02-12 18:24 ` Dmitriy Monakhov [this message]
2007-02-21 20:13 ` [PATCH] eCryptfs: resolve lower page unlocking problem Michael Halcrow

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=87bqjzcjzg.fsf@sw.ru \
    --to=dmonakhov@sw.ru \
    --cc=dmonakhov@openvz.org \
    --cc=ecryptfs-devel@lists.sourceforge.net \
    --cc=linux-kernel@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.