Re: [PATCH v3] ceph: optimize memory usage

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

 



On Tue, Mar 13, 2018 at 10:42 AM, Chengguang Xu <cgxu519@xxxxxxx> wrote:
> In current code, regular file and directory use same struct
> ceph_file_info to store fs specific data so the struct has to
> include some fields which are only used for directory
> (e.g., readdir related info), when having plenty of regular files,
> it will lead to memory waste.
>
> This patch introduces dedicated ceph_dir_file_info cache for
> directory and delete readdir related thins from ceph_file_info,
> so that regular file does not include those unused fields anymore.
> Also, chagned to manipulate fscache after reuglar file acquires
> ceph_file_info successfully.
>

Applied with some modifications. I remove fscache related change, pass
'dfi' directly to readdir helper functions.

Regards
Yan, Zheng


> Signed-off-by: Chengguang Xu <cgxu519@xxxxxxx>
> ---
> Changes since v2:
> - Rebase to testing tree.
> - Introduce dfi only for readdir related things.
>
> Changes since v1:
> - Modify ceph_dir_file_info to include ceph_file_info instead of pointing to it.
>
>  fs/ceph/dir.c                | 161 +++++++++++++++++++++++--------------------
>  fs/ceph/file.c               |  91 ++++++++++++++++--------
>  fs/ceph/super.c              |   8 +++
>  fs/ceph/super.h              |   9 +++
>  include/linux/ceph/libceph.h |   1 +
>  5 files changed, 169 insertions(+), 101 deletions(-)
>
> diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
> index 51d09a3..be485c1 100644
> --- a/fs/ceph/dir.c
> +++ b/fs/ceph/dir.c
> @@ -105,15 +105,17 @@ static int fpos_cmp(loff_t l, loff_t r)
>  static int note_last_dentry(struct ceph_file_info *fi, const char *name,
>                                 int len, unsigned int next_offset)
>  {
> +       struct ceph_dir_file_info *dfi = CEPH_DFI(fi);
> +
>         char *buf = kmalloc(len+1, GFP_KERNEL);
>         if (!buf)
>                 return -ENOMEM;
> -       kfree(fi->last_name);
> -       fi->last_name = buf;
> -       memcpy(fi->last_name, name, len);
> -       fi->last_name[len] = 0;
> -       fi->next_offset = next_offset;
> -       dout("note_last_dentry '%s'\n", fi->last_name);
> +       kfree(dfi->last_name);
> +       dfi->last_name = buf;
> +       memcpy(dfi->last_name, name, len);
> +       dfi->last_name[len] = 0;
> +       dfi->next_offset = next_offset;
> +       dout("note_last_dentry '%s'\n", dfi->last_name);
>         return 0;
>  }
>
> @@ -176,6 +178,7 @@ static int __dcache_readdir(struct file *file,  struct dir_context *ctx,
>                             int shared_gen)
>  {
>         struct ceph_file_info *fi = file->private_data;
> +       struct ceph_dir_file_info *dfi = CEPH_DFI(fi);
>         struct dentry *parent = file->f_path.dentry;
>         struct inode *dir = d_inode(parent);
>         struct dentry *dentry, *last = NULL;
> @@ -280,9 +283,9 @@ static int __dcache_readdir(struct file *file,  struct dir_context *ctx,
>                         err = ret;
>                 dput(last);
>                 /* last_name no longer match cache index */
> -               if (fi->readdir_cache_idx >= 0) {
> -                       fi->readdir_cache_idx = -1;
> -                       fi->dir_release_count = 0;
> +               if (dfi->readdir_cache_idx >= 0) {
> +                       dfi->readdir_cache_idx = -1;
> +                       dfi->dir_release_count = 0;
>                 }
>         }
>         return err;
> @@ -290,17 +293,20 @@ static int __dcache_readdir(struct file *file,  struct dir_context *ctx,
>
>  static bool need_send_readdir(struct ceph_file_info *fi, loff_t pos)
>  {
> -       if (!fi->last_readdir)
> +       struct ceph_dir_file_info *dfi = CEPH_DFI(fi);
> +
> +       if (!dfi->last_readdir)
>                 return true;
>         if (is_hash_order(pos))
> -               return !ceph_frag_contains_value(fi->frag, fpos_hash(pos));
> +               return !ceph_frag_contains_value(dfi->frag, fpos_hash(pos));
>         else
> -               return fi->frag != fpos_frag(pos);
> +               return dfi->frag != fpos_frag(pos);
>  }
>
>  static int ceph_readdir(struct file *file, struct dir_context *ctx)
>  {
>         struct ceph_file_info *fi = file->private_data;
> +       struct ceph_dir_file_info *dfi = CEPH_DFI(fi);
>         struct inode *inode = file_inode(file);
>         struct ceph_inode_info *ci = ceph_inode(inode);
>         struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
> @@ -358,9 +364,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>                         CEPH_MDS_OP_LSSNAP : CEPH_MDS_OP_READDIR;
>
>                 /* discard old result, if any */
> -               if (fi->last_readdir) {
> -                       ceph_mdsc_put_request(fi->last_readdir);
> -                       fi->last_readdir = NULL;
> +               if (dfi->last_readdir) {
> +                       ceph_mdsc_put_request(dfi->last_readdir);
> +                       dfi->last_readdir = NULL;
>                 }
>
>                 if (is_hash_order(ctx->pos)) {
> @@ -374,7 +380,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>                 }
>
>                 dout("readdir fetching %llx.%llx frag %x offset '%s'\n",
> -                    ceph_vinop(inode), frag, fi->last_name);
> +                    ceph_vinop(inode), frag, dfi->last_name);
>                 req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
>                 if (IS_ERR(req))
>                         return PTR_ERR(req);
> @@ -390,8 +396,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>                         __set_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags);
>                         req->r_inode_drop = CEPH_CAP_FILE_EXCL;
>                 }
> -               if (fi->last_name) {
> -                       req->r_path2 = kstrdup(fi->last_name, GFP_KERNEL);
> +               if (dfi->last_name) {
> +                       req->r_path2 = kstrdup(dfi->last_name, GFP_KERNEL);
>                         if (!req->r_path2) {
>                                 ceph_mdsc_put_request(req);
>                                 return -ENOMEM;
> @@ -401,10 +407,10 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>                                 cpu_to_le32(fpos_hash(ctx->pos));
>                 }
>
> -               req->r_dir_release_cnt = fi->dir_release_count;
> -               req->r_dir_ordered_cnt = fi->dir_ordered_count;
> -               req->r_readdir_cache_idx = fi->readdir_cache_idx;
> -               req->r_readdir_offset = fi->next_offset;
> +               req->r_dir_release_cnt = dfi->dir_release_count;
> +               req->r_dir_ordered_cnt = dfi->dir_ordered_count;
> +               req->r_readdir_cache_idx = dfi->readdir_cache_idx;
> +               req->r_readdir_offset = dfi->next_offset;
>                 req->r_args.readdir.frag = cpu_to_le32(frag);
>                 req->r_args.readdir.flags =
>                                 cpu_to_le16(CEPH_READDIR_REPLY_BITFLAGS);
> @@ -428,35 +434,35 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>                 if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
>                         frag = le32_to_cpu(rinfo->dir_dir->frag);
>                         if (!rinfo->hash_order) {
> -                               fi->next_offset = req->r_readdir_offset;
> +                               dfi->next_offset = req->r_readdir_offset;
>                                 /* adjust ctx->pos to beginning of frag */
>                                 ctx->pos = ceph_make_fpos(frag,
> -                                                         fi->next_offset,
> +                                                         dfi->next_offset,
>                                                           false);
>                         }
>                 }
>
> -               fi->frag = frag;
> -               fi->last_readdir = req;
> +               dfi->frag = frag;
> +               dfi->last_readdir = req;
>
>                 if (test_bit(CEPH_MDS_R_DID_PREPOPULATE, &req->r_req_flags)) {
> -                       fi->readdir_cache_idx = req->r_readdir_cache_idx;
> -                       if (fi->readdir_cache_idx < 0) {
> +                       dfi->readdir_cache_idx = req->r_readdir_cache_idx;
> +                       if (dfi->readdir_cache_idx < 0) {
>                                 /* preclude from marking dir ordered */
> -                               fi->dir_ordered_count = 0;
> +                               dfi->dir_ordered_count = 0;
>                         } else if (ceph_frag_is_leftmost(frag) &&
> -                                  fi->next_offset == 2) {
> +                                  dfi->next_offset == 2) {
>                                 /* note dir version at start of readdir so
>                                  * we can tell if any dentries get dropped */
> -                               fi->dir_release_count = req->r_dir_release_cnt;
> -                               fi->dir_ordered_count = req->r_dir_ordered_cnt;
> +                               dfi->dir_release_count = req->r_dir_release_cnt;
> +                               dfi->dir_ordered_count = req->r_dir_ordered_cnt;
>                         }
>                 } else {
>                         dout("readdir !did_prepopulate\n");
>                         /* disable readdir cache */
> -                       fi->readdir_cache_idx = -1;
> +                       dfi->readdir_cache_idx = -1;
>                         /* preclude from marking dir complete */
> -                       fi->dir_release_count = 0;
> +                       dfi->dir_release_count = 0;
>                 }
>
>                 /* note next offset and last dentry name */
> @@ -470,14 +476,14 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>                         if (err)
>                                 return err;
>                 } else if (req->r_reply_info.dir_end) {
> -                       fi->next_offset = 2;
> +                       dfi->next_offset = 2;
>                         /* keep last name */
>                 }
>         }
>
> -       rinfo = &fi->last_readdir->r_reply_info;
> +       rinfo = &dfi->last_readdir->r_reply_info;
>         dout("readdir frag %x num %d pos %llx chunk first %llx\n",
> -            fi->frag, rinfo->dir_nr, ctx->pos,
> +            dfi->frag, rinfo->dir_nr, ctx->pos,
>              rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL);
>
>         i = 0;
> @@ -521,27 +527,28 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>                 ctx->pos++;
>         }
>
> -       ceph_mdsc_put_request(fi->last_readdir);
> -       fi->last_readdir = NULL;
> +       ceph_mdsc_put_request(dfi->last_readdir);
> +       dfi->last_readdir = NULL;
>
> -       if (fi->next_offset > 2) {
> -               frag = fi->frag;
> +       if (dfi->next_offset > 2) {
> +               frag = dfi->frag;
>                 goto more;
>         }
>
>         /* more frags? */
> -       if (!ceph_frag_is_rightmost(fi->frag)) {
> -               frag = ceph_frag_next(fi->frag);
> +       if (!ceph_frag_is_rightmost(dfi->frag)) {
> +               frag = ceph_frag_next(dfi->frag);
>                 if (is_hash_order(ctx->pos)) {
>                         loff_t new_pos = ceph_make_fpos(ceph_frag_value(frag),
> -                                                       fi->next_offset, true);
> +                                                       dfi->next_offset, true);
>                         if (new_pos > ctx->pos)
>                                 ctx->pos = new_pos;
>                         /* keep last_name */
>                 } else {
> -                       ctx->pos = ceph_make_fpos(frag, fi->next_offset, false);
> -                       kfree(fi->last_name);
> -                       fi->last_name = NULL;
> +                       ctx->pos = ceph_make_fpos(frag, dfi->next_offset,
> +                                                       false);
> +                       kfree(dfi->last_name);
> +                       dfi->last_name = NULL;
>                 }
>                 dout("readdir next frag is %x\n", frag);
>                 goto more;
> @@ -553,20 +560,22 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>          * were released during the whole readdir, and we should have
>          * the complete dir contents in our cache.
>          */
> -       if (atomic64_read(&ci->i_release_count) == fi->dir_release_count) {
> +       if (atomic64_read(&ci->i_release_count) ==
> +                                       dfi->dir_release_count) {
>                 spin_lock(&ci->i_ceph_lock);
> -               if (fi->dir_ordered_count == atomic64_read(&ci->i_ordered_count)) {
> +               if (dfi->dir_ordered_count ==
> +                               atomic64_read(&ci->i_ordered_count)) {
>                         dout(" marking %p complete and ordered\n", inode);
>                         /* use i_size to track number of entries in
>                          * readdir cache */
> -                       BUG_ON(fi->readdir_cache_idx < 0);
> -                       i_size_write(inode, fi->readdir_cache_idx *
> +                       BUG_ON(dfi->readdir_cache_idx < 0);
> +                       i_size_write(inode, dfi->readdir_cache_idx *
>                                      sizeof(struct dentry*));
>                 } else {
>                         dout(" marking %p complete\n", inode);
>                 }
> -               __ceph_dir_set_complete(ci, fi->dir_release_count,
> -                                       fi->dir_ordered_count);
> +               __ceph_dir_set_complete(ci, dfi->dir_release_count,
> +                                       dfi->dir_ordered_count);
>                 spin_unlock(&ci->i_ceph_lock);
>         }
>
> @@ -576,15 +585,17 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
>
>  static void reset_readdir(struct ceph_file_info *fi)
>  {
> -       if (fi->last_readdir) {
> -               ceph_mdsc_put_request(fi->last_readdir);
> -               fi->last_readdir = NULL;
> +       struct ceph_dir_file_info *dfi = CEPH_DFI(fi);
> +
> +       if (dfi->last_readdir) {
> +               ceph_mdsc_put_request(dfi->last_readdir);
> +               dfi->last_readdir = NULL;
>         }
> -       kfree(fi->last_name);
> -       fi->last_name = NULL;
> -       fi->dir_release_count = 0;
> -       fi->readdir_cache_idx = -1;
> -       fi->next_offset = 2;  /* compensate for . and .. */
> +       kfree(dfi->last_name);
> +       dfi->last_name = NULL;
> +       dfi->dir_release_count = 0;
> +       dfi->readdir_cache_idx = -1;
> +       dfi->next_offset = 2;  /* compensate for . and .. */
>         fi->flags &= ~CEPH_F_ATEND;
>  }
>
> @@ -594,6 +605,7 @@ static void reset_readdir(struct ceph_file_info *fi)
>   */
>  static bool need_reset_readdir(struct ceph_file_info *fi, loff_t new_pos)
>  {
> +       struct ceph_dir_file_info *dfi = CEPH_DFI(fi);
>         struct ceph_mds_reply_info_parsed *rinfo;
>         loff_t chunk_offset;
>         if (new_pos == 0)
> @@ -601,10 +613,10 @@ static bool need_reset_readdir(struct ceph_file_info *fi, loff_t new_pos)
>         if (is_hash_order(new_pos)) {
>                 /* no need to reset last_name for a forward seek when
>                  * dentries are sotred in hash order */
> -       } else if (fi->frag != fpos_frag(new_pos)) {
> +       } else if (dfi->frag != fpos_frag(new_pos)) {
>                 return true;
>         }
> -       rinfo = fi->last_readdir ? &fi->last_readdir->r_reply_info : NULL;
> +       rinfo = dfi->last_readdir ? &dfi->last_readdir->r_reply_info : NULL;
>         if (!rinfo || !rinfo->dir_nr)
>                 return true;
>         chunk_offset = rinfo->dir_entries[0].offset;
> @@ -615,6 +627,7 @@ static bool need_reset_readdir(struct ceph_file_info *fi, loff_t new_pos)
>  static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
>  {
>         struct ceph_file_info *fi = file->private_data;
> +       struct ceph_dir_file_info *dfi = CEPH_DFI(fi);
>         struct inode *inode = file->f_mapping->host;
>         loff_t retval;
>
> @@ -638,8 +651,8 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
>                 } else if (is_hash_order(offset) && offset > file->f_pos) {
>                         /* for hash offset, we don't know if a forward seek
>                          * is within same frag */
> -                       fi->dir_release_count = 0;
> -                       fi->readdir_cache_idx = -1;
> +                       dfi->dir_release_count = 0;
> +                       dfi->readdir_cache_idx = -1;
>                 }
>
>                 if (offset != file->f_pos) {
> @@ -1370,7 +1383,7 @@ static void ceph_d_prune(struct dentry *dentry)
>  static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
>                              loff_t *ppos)
>  {
> -       struct ceph_file_info *fi = file->private_data;
> +       struct ceph_dir_file_info *dfi = file->private_data;
>         struct inode *inode = file_inode(file);
>         struct ceph_inode_info *ci = ceph_inode(inode);
>         int left;
> @@ -1379,12 +1392,12 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
>         if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
>                 return -EISDIR;
>
> -       if (!fi->dir_info) {
> -               fi->dir_info = kmalloc(bufsize, GFP_KERNEL);
> -               if (!fi->dir_info)
> +       if (!dfi->dir_info) {
> +               dfi->dir_info = kmalloc(bufsize, GFP_KERNEL);
> +               if (!dfi->dir_info)
>                         return -ENOMEM;
> -               fi->dir_info_len =
> -                       snprintf(fi->dir_info, bufsize,
> +               dfi->dir_info_len =
> +                       snprintf(dfi->dir_info, bufsize,
>                                 "entries:   %20lld\n"
>                                 " files:    %20lld\n"
>                                 " subdirs:  %20lld\n"
> @@ -1404,10 +1417,10 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
>                                 (long)ci->i_rctime.tv_nsec);
>         }
>
> -       if (*ppos >= fi->dir_info_len)
> +       if (*ppos >= dfi->dir_info_len)
>                 return 0;
> -       size = min_t(unsigned int, size, fi->dir_info_len-*ppos);
> -       left = copy_to_user(buf, fi->dir_info + *ppos, size);
> +       size = min_t(unsigned int, size, dfi->dir_info_len-*ppos);
> +       left = copy_to_user(buf, dfi->dir_info + *ppos, size);
>         if (left == size)
>                 return -EFAULT;
>         *ppos += (size - left);
> diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> index 2de7031..c782beb 100644
> --- a/fs/ceph/file.c
> +++ b/fs/ceph/file.c
> @@ -95,36 +95,61 @@ static __le32 ceph_flags_sys2wire(u32 flags)
>         return req;
>  }
>
> +static int ceph_init_file_info(struct inode *inode, struct file *file,
> +                                       int fmode, bool isdir)
> +{
> +       struct ceph_file_info *fi;
> +       struct ceph_dir_file_info *dfi;
> +
> +       dout("%s %p %p 0%o (%s)\n", __func__, inode, file,
> +                       inode->i_mode, isdir ? "dir" : "regular");
> +       BUG_ON(inode->i_fop->release != ceph_release);
> +
> +       if (isdir) {
> +               dfi = kmem_cache_zalloc(ceph_dir_file_cachep, GFP_KERNEL);
> +               if (!dfi) {
> +                       ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
> +                       return -ENOMEM;
> +               }
> +
> +               file->private_data = dfi;
> +               fi = &dfi->file_info;
> +               dfi->next_offset = 2;
> +               dfi->readdir_cache_idx = -1;
> +       } else {
> +               fi = kmem_cache_zalloc(ceph_file_cachep, GFP_KERNEL);
> +               if (!fi) {
> +                       ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
> +                       return -ENOMEM;
> +               }
> +
> +               file->private_data = fi;
> +               ceph_fscache_register_inode_cookie(inode);
> +               ceph_fscache_file_set_cookie(inode, file);
> +       }
> +
> +       fi->fmode = fmode;
> +       spin_lock_init(&fi->rw_contexts_lock);
> +       INIT_LIST_HEAD(&fi->rw_contexts);
> +
> +       return 0;
> +}
> +
>  /*
>   * initialize private struct file data.
>   * if we fail, clean up by dropping fmode reference on the ceph_inode
>   */
>  static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
>  {
> -       struct ceph_file_info *fi;
>         int ret = 0;
>
>         switch (inode->i_mode & S_IFMT) {
>         case S_IFREG:
> -               ceph_fscache_register_inode_cookie(inode);
> -               ceph_fscache_file_set_cookie(inode, file);
>         case S_IFDIR:
> -               dout("init_file %p %p 0%o (regular)\n", inode, file,
> -                    inode->i_mode);
> -               fi = kmem_cache_zalloc(ceph_file_cachep, GFP_KERNEL);
> -               if (!fi) {
> -                       ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
> -                       return -ENOMEM;
> -               }
> -               fi->fmode = fmode;
> -
> -               spin_lock_init(&fi->rw_contexts_lock);
> -               INIT_LIST_HEAD(&fi->rw_contexts);
> -
> -               fi->next_offset = 2;
> -               fi->readdir_cache_idx = -1;
> -               file->private_data = fi;
> -               BUG_ON(inode->i_fop->release != ceph_release);
> +               ret = ceph_init_file_info(inode, file, fmode,
> +                                               S_ISDIR(inode->i_mode));
> +               if (ret)
> +                       return ret;
>                 break;
>
>         case S_IFLNK:
> @@ -399,15 +424,27 @@ int ceph_release(struct inode *inode, struct file *file)
>  {
>         struct ceph_inode_info *ci = ceph_inode(inode);
>         struct ceph_file_info *fi = file->private_data;
> +       struct ceph_dir_file_info *dfi;
>
> -       dout("release inode %p file %p\n", inode, file);
> -       ceph_put_fmode(ci, fi->fmode);
> -       if (fi->last_readdir)
> -               ceph_mdsc_put_request(fi->last_readdir);
> -       kfree(fi->last_name);
> -       kfree(fi->dir_info);
> -       WARN_ON(!list_empty(&fi->rw_contexts));
> -       kmem_cache_free(ceph_file_cachep, fi);
> +       if (S_ISDIR(inode->i_mode)) {
> +               dout("release inode %p dir file %p\n", inode, file);
> +               WARN_ON(!list_empty(&fi->rw_contexts));
> +
> +               dfi = CEPH_DFI(fi);
> +               ceph_put_fmode(ci, fi->fmode);
> +
> +               if (dfi->last_readdir)
> +                       ceph_mdsc_put_request(dfi->last_readdir);
> +               kfree(dfi->last_name);
> +               kfree(dfi->dir_info);
> +               kmem_cache_free(ceph_dir_file_cachep, dfi);
> +       } else {
> +               dout("release inode %p regular file %p\n", inode, file);
> +               WARN_ON(!list_empty(&fi->rw_contexts));
> +
> +               ceph_put_fmode(ci, fi->fmode);
> +               kmem_cache_free(ceph_file_cachep, fi);
> +       }
>
>         /* wake up anyone waiting for caps on this inode */
>         wake_up_all(&ci->i_cap_wq);
> diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> index 880e83e..286e8db 100644
> --- a/fs/ceph/super.c
> +++ b/fs/ceph/super.c
> @@ -699,6 +699,7 @@ static void destroy_fs_client(struct ceph_fs_client *fsc)
>  struct kmem_cache *ceph_cap_flush_cachep;
>  struct kmem_cache *ceph_dentry_cachep;
>  struct kmem_cache *ceph_file_cachep;
> +struct kmem_cache *ceph_dir_file_cachep;
>
>  static void ceph_inode_init_once(void *foo)
>  {
> @@ -735,6 +736,10 @@ static int __init init_caches(void)
>         if (!ceph_file_cachep)
>                 goto bad_file;
>
> +       ceph_dir_file_cachep = KMEM_CACHE(ceph_dir_file_info, SLAB_MEM_SPREAD);
> +       if (!ceph_dir_file_cachep)
> +               goto bad_dir_file;
> +
>         error = ceph_fscache_register();
>         if (error)
>                 goto bad_fscache;
> @@ -742,6 +747,8 @@ static int __init init_caches(void)
>         return 0;
>
>  bad_fscache:
> +       kmem_cache_destroy(ceph_dir_file_cachep);
> +bad_dir_file:
>         kmem_cache_destroy(ceph_file_cachep);
>  bad_file:
>         kmem_cache_destroy(ceph_dentry_cachep);
> @@ -767,6 +774,7 @@ static void destroy_caches(void)
>         kmem_cache_destroy(ceph_cap_flush_cachep);
>         kmem_cache_destroy(ceph_dentry_cachep);
>         kmem_cache_destroy(ceph_file_cachep);
> +       kmem_cache_destroy(ceph_dir_file_cachep);
>
>         ceph_fscache_unregister();
>  }
> diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> index 4e619de..2e5ff4a 100644
> --- a/fs/ceph/super.h
> +++ b/fs/ceph/super.h
> @@ -678,6 +678,10 @@ struct ceph_file_info {
>
>         spinlock_t rw_contexts_lock;
>         struct list_head rw_contexts;
> +};
> +
> +struct ceph_dir_file_info {
> +       struct ceph_file_info file_info;
>
>         /* readdir: position within the dir */
>         u32 frag;
> @@ -695,6 +699,11 @@ struct ceph_file_info {
>         int dir_info_len;
>  };
>
> +static inline struct ceph_dir_file_info *CEPH_DFI(struct ceph_file_info *fi)
> +{
> +       return container_of(fi, struct ceph_dir_file_info, file_info);
> +}
> +
>  struct ceph_rw_context {
>         struct list_head list;
>         struct task_struct *thread;
> diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> index c2ec44c..49c93b9 100644
> --- a/include/linux/ceph/libceph.h
> +++ b/include/linux/ceph/libceph.h
> @@ -262,6 +262,7 @@ static inline int calc_pages_for(u64 off, u64 len)
>  extern struct kmem_cache *ceph_cap_flush_cachep;
>  extern struct kmem_cache *ceph_dentry_cachep;
>  extern struct kmem_cache *ceph_file_cachep;
> +extern struct kmem_cache *ceph_dir_file_cachep;
>
>  /* ceph_common.c */
>  extern bool libceph_compatible(void *data);
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux