Re: [PATCH 34/41] fallthru: tmpfs fallthru support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In message <1256152779-10054-35-git-send-email-vaurora@xxxxxxxxxx>, Valerie Aurora writes:
> Add support for fallthru directory entries to tmpfs

Need to CC tmpfs maintainers here.

> XXX - Makes up inode number for dirent
> 
> Signed-off-by: Valerie Aurora <vaurora@xxxxxxxxxx>
> ---
>  fs/dcache.c |    3 +-
>  fs/libfs.c  |   21 +++++++++++++++++--
>  mm/shmem.c  |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
>  3 files changed, 73 insertions(+), 11 deletions(-)
> 
> diff --git a/fs/dcache.c b/fs/dcache.c
> index ca8a661..8ef2d89 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -2292,7 +2292,8 @@ resume:
>  		struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
>  		next = tmp->next;
>  		if (d_unhashed(dentry)||(!dentry->d_inode &&
> -					 !d_is_whiteout(dentry)))
> +					 !d_is_whiteout(dentry) &&
> +					 !d_is_fallthru(dentry)))
>  			continue;
>  		if (!list_empty(&dentry->d_subdirs)) {
>  			this_parent = dentry;
> diff --git a/fs/libfs.c b/fs/libfs.c
> index dcec3d3..01f3e73 100644
> --- a/fs/libfs.c
> +++ b/fs/libfs.c
> @@ -133,6 +133,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
>  	struct dentry *cursor = filp->private_data;
>  	struct list_head *p, *q = &cursor->d_u.d_child;
>  	ino_t ino;
> +	int d_type;
>  	int i = filp->f_pos;
>  
>  	switch (i) {
> @@ -158,14 +159,28 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
>  			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
>  				struct dentry *next;
>  				next = list_entry(p, struct dentry, d_u.d_child);
> -				if (d_unhashed(next) || !next->d_inode)
> +				if (d_unhashed(next) || (!next->d_inode && !d_is_fallthru(next)))
>  					continue;
>  
> +				if (d_is_fallthru(next)) {
> +					/* XXX We don't know the inode
> +					 * number of the directory
> +					 * entry in the underlying
> +					 * file system.  Should look
> +					 * it up, either on fallthru
> +					 * creation at first readdir
> +					 * or now at filldir time. */
> +					ino = 123; /* Made up ino */

Ok, so here it's 123, as in ext2, but not jffs2, who had it set to 100...

> +					d_type = DT_UNKNOWN;
> +				} else {
> +					ino = next->d_inode->i_ino;
> +					d_type = dt_type(next->d_inode);
> +				}
> +
>  				spin_unlock(&dcache_lock);
>  				if (filldir(dirent, next->d_name.name, 
>  					    next->d_name.len, filp->f_pos, 
> -					    next->d_inode->i_ino, 
> -					    dt_type(next->d_inode)) < 0)
> +					    ino, d_type) < 0)
>  					return 0;
>  				spin_lock(&dcache_lock);
>  				/* next is still alive */
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 2faa14b..4f4b4b6 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1798,8 +1798,7 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry);
>  static int shmem_unlink(struct inode *dir, struct dentry *dentry);
>  
>  /*
> - * This is the whiteout support for tmpfs. It uses one singleton whiteout
> - * inode per superblock thus it is very similar to shmem_link().
> + * Create a dentry to signify a whiteout.
>   */
>  static int shmem_whiteout(struct inode *dir, struct dentry *old_dentry,
>  			  struct dentry *new_dentry)
> @@ -1830,8 +1829,10 @@ static int shmem_whiteout(struct inode *dir, struct dentry *old_dentry,
>  		spin_unlock(&sbinfo->stat_lock);
>  	}
>  
> -	if (old_dentry->d_inode) {
> -		if (S_ISDIR(old_dentry->d_inode->i_mode))
> +	if (old_dentry->d_inode || d_is_fallthru(old_dentry)) {
> +		/* A fallthru for a dir is treated like a regular link */
> +		if (old_dentry->d_inode &&
> +		    S_ISDIR(old_dentry->d_inode->i_mode))
>  			shmem_rmdir(dir, old_dentry);
>  		else
>  			shmem_unlink(dir, old_dentry);
> @@ -1848,6 +1849,48 @@ static int shmem_whiteout(struct inode *dir, struct dentry *old_dentry,
>  }
>  
>  static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry,
> +				struct inode *inode);
> +
> +/*
> + * Create a dentry to signify a fallthru.  A fallthru in tmpfs is the
> + * logical equivalent of an in-kernel readdir() cache.  It can't be
> + * deleted until the file system is unmounted.
> + */
> +static int shmem_fallthru(struct inode *dir, struct dentry *dentry)
> +{
> +	struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb);
> +
> +	/* FIXME: this is stupid */
> +	if (!(dir->i_sb->s_flags & MS_WHITEOUT))
> +		return -EPERM;
> +
> +	if (dentry->d_inode || d_is_fallthru(dentry) || d_is_whiteout(dentry))
> +		return -EEXIST;
> +
> +	/*
> +	 * Each new link needs a new dentry, pinning lowmem, and tmpfs
> +	 * dentries cannot be pruned until they are unlinked.
> +	 */
> +	if (sbinfo->max_inodes) {
> +		spin_lock(&sbinfo->stat_lock);
> +		if (!sbinfo->free_inodes) {
> +			spin_unlock(&sbinfo->stat_lock);
> +			return -ENOSPC;
> +		}
> +		sbinfo->free_inodes--;
> +		spin_unlock(&sbinfo->stat_lock);
> +	}
> +
> +	shmem_d_instantiate(dir, dentry, NULL);
> +	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
> +
> +	spin_lock(&dentry->d_lock);
> +	dentry->d_flags |= DCACHE_FALLTHRU;
> +	spin_unlock(&dentry->d_lock);
> +	return 0;
> +}
> +
> +static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry,
>  				struct inode *inode)
>  {
>  	if (d_is_whiteout(dentry)) {
> @@ -1855,14 +1898,15 @@ static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry,
>  		shmem_free_inode(dir->i_sb);
>  		if (S_ISDIR(inode->i_mode))
>  			inode->i_mode |= S_OPAQUE;
> +	} else if (d_is_fallthru(dentry)) {
> +		shmem_free_inode(dir->i_sb);
>  	} else {
>  		/* New dentry */
>  		dir->i_size += BOGO_DIRENT_SIZE;
>  		dget(dentry); /* Extra count - pin the dentry in core */
>  	}
> -	/* Will clear DCACHE_WHITEOUT flag */
> +	/* Will clear DCACHE_WHITEOUT and DCACHE_FALLTHRU flags */
>  	d_instantiate(dentry, inode);
> -
>  }
>  /*
>   * File creation. Allocate an inode, and we're done..
> @@ -1947,7 +1991,8 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
>  {
>  	struct inode *inode = dentry->d_inode;
>  
> -	if (d_is_whiteout(dentry) || (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)))
> +	if (d_is_whiteout(dentry) || d_is_fallthru(dentry) ||
> +	    (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)))
>  		shmem_free_inode(dir->i_sb);

I'd reorder this || condition above so the more common sub-conditions to be
true, show up first (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode).
d_is_whatever should go last.

>  
>  	if (inode) {
> @@ -2583,6 +2628,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
>  	.mknod		= shmem_mknod,
>  	.rename		= shmem_rename,
>  	.whiteout       = shmem_whiteout,
> +	.fallthru       = shmem_fallthru,
>  #endif
>  #ifdef CONFIG_TMPFS_POSIX_ACL
>  	.setattr	= shmem_notify_change,
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Erez.
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux