lkml.org 
[lkml]   [2009]   [Nov]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 34/41] fallthru: tmpfs fallthru support
    In message <1256152779-10054-35-git-send-email-vaurora@redhat.com>, 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@redhat.com>
    > ---
    > 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@vger.kernel.org
    > More majordomo info at http://vger.kernel.org/majordomo-info.html

    Erez.


    \
     
     \ /
      Last update: 2009-12-01 05:21    [W:0.034 / U:59.684 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site