lkml.org 
[lkml]   [2012]   [Mar]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 13/16] ceph: implement i_op->atomic_open() and i_op->atomic_create()
    Date
    From: Miklos Szeredi <mszeredi@suse.cz>

    Instead of calling ceph_lookup_open() from ->lookup and ->create, call it from
    ->atomic_open and ->atomic_create.

    CEPH does non-create open in ->atomic_open and create-open in ->atomic_create.
    To prevent unnecessary call to ->atomic_open the FS_NO_LOOKUP_CREATE flag is set
    in the filesystem flags to only call ->atomic_open on non-create opens.

    Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
    ---
    fs/ceph/dir.c | 68 ++++++++++++++++++++++++++++++++++--------------------
    fs/ceph/file.c | 21 ++++++++---------
    fs/ceph/super.h | 5 ++-
    3 files changed, 56 insertions(+), 38 deletions(-)

    diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
    index c4b7832..75df600 100644
    --- a/fs/ceph/dir.c
    +++ b/fs/ceph/dir.c
    @@ -594,14 +594,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
    if (err < 0)
    return ERR_PTR(err);

    - /* open (but not create!) intent? */
    - if (nd &&
    - (nd->flags & LOOKUP_OPEN) &&
    - !(nd->intent.open.flags & O_CREAT)) {
    - int mode = nd->intent.open.create_mode & ~current->fs->umask;
    - return ceph_lookup_open(dir, dentry, nd, mode);
    - }
    -
    /* can we conclude ENOENT locally? */
    if (dentry->d_inode == NULL) {
    struct ceph_inode_info *ci = ceph_inode(dir);
    @@ -642,6 +634,47 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
    return dentry;
    }

    +struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry,
    + struct opendata *od, unsigned flags, umode_t mode,
    + bool *created)
    +{
    + int err;
    + struct dentry *res = NULL;
    + struct file *filp;
    +
    + if (!(flags & O_CREAT)) {
    + if (dentry->d_name.len > NAME_MAX)
    + return ERR_PTR(-ENAMETOOLONG);
    +
    + err = ceph_init_dentry(dentry);
    + if (err < 0)
    + return ERR_PTR(err);
    +
    + return ceph_lookup_open(dir, dentry, od, flags, mode);
    + }
    +
    + if (d_unhashed(dentry)) {
    + res = ceph_lookup(dir, dentry, NULL);
    + if (IS_ERR(res))
    + return ERR_CAST(res);
    +
    + if (res)
    + dentry = res;
    + }
    +
    + /* We don't deal with positive dentries here */
    + if (dentry->d_inode) {
    + finish_no_open(od, res);
    + return NULL;
    + }
    +
    + *created = true;
    + filp = ceph_lookup_open(dir, dentry, od, flags, mode);
    + dput(res);
    +
    + return filp;
    +}
    +
    /*
    * If we do a create but get no trace back from the MDS, follow up with
    * a lookup (the VFS expects us to link up the provided dentry).
    @@ -702,23 +735,7 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
    static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode,
    struct nameidata *nd)
    {
    - dout("create in dir %p dentry %p name '%.*s'\n",
    - dir, dentry, dentry->d_name.len, dentry->d_name.name);
    -
    - if (ceph_snap(dir) != CEPH_NOSNAP)
    - return -EROFS;
    -
    - if (nd) {
    - BUG_ON((nd->flags & LOOKUP_OPEN) == 0);
    - dentry = ceph_lookup_open(dir, dentry, nd, mode);
    - /* hrm, what should i do here if we get aliased? */
    - if (IS_ERR(dentry))
    - return PTR_ERR(dentry);
    - return 0;
    - }
    -
    - /* fall back to mknod */
    - return ceph_mknod(dir, dentry, (mode & ~S_IFMT) | S_IFREG, 0);
    + return ceph_mknod(dir, dentry, mode, 0);
    }

    static int ceph_symlink(struct inode *dir, struct dentry *dentry,
    @@ -1357,6 +1374,7 @@ const struct inode_operations ceph_dir_iops = {
    .rmdir = ceph_unlink,
    .rename = ceph_rename,
    .create = ceph_create,
    + .atomic_open = ceph_atomic_open,
    };

    const struct dentry_operations ceph_dentry_ops = {
    diff --git a/fs/ceph/file.c b/fs/ceph/file.c
    index 2fe9a3e..bf35158 100644
    --- a/fs/ceph/file.c
    +++ b/fs/ceph/file.c
    @@ -214,21 +214,15 @@ out:
    * may_open() fails, the struct *file gets cleaned up (i.e.
    * ceph_release gets called). So fear not!
    */
    -/*
    - * flags
    - * path_lookup_open -> LOOKUP_OPEN
    - * path_lookup_create -> LOOKUP_OPEN|LOOKUP_CREATE
    - */
    -struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
    - struct nameidata *nd, int mode)
    +struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
    + struct opendata *od, unsigned flags, umode_t mode)
    {
    struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
    struct ceph_mds_client *mdsc = fsc->mdsc;
    - struct file *file;
    + struct file *file = NULL;
    struct ceph_mds_request *req;
    struct dentry *ret;
    int err;
    - int flags = nd->intent.open.flags;

    dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n",
    dentry, dentry->d_name.len, dentry->d_name.name, flags, mode);
    @@ -254,14 +248,19 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
    err = ceph_handle_notrace_create(dir, dentry);
    if (err)
    goto out;
    - file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open);
    + file = finish_open(od, req->r_dentry, ceph_open);
    if (IS_ERR(file))
    err = PTR_ERR(file);
    out:
    ret = ceph_finish_lookup(req, dentry, err);
    ceph_mdsc_put_request(req);
    dout("ceph_lookup_open result=%p\n", ret);
    - return ret;
    +
    + if (IS_ERR(ret))
    + return ERR_CAST(ret);
    +
    + dput(ret);
    + return err ? ERR_PTR(err) : file;
    }

    int ceph_release(struct inode *inode, struct file *file)
    diff --git a/fs/ceph/super.h b/fs/ceph/super.h
    index c6b2cba..4e83114 100644
    --- a/fs/ceph/super.h
    +++ b/fs/ceph/super.h
    @@ -804,8 +804,9 @@ extern int ceph_copy_from_page_vector(struct page **pages,
    loff_t off, size_t len);
    extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
    extern int ceph_open(struct inode *inode, struct file *file);
    -extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
    - struct nameidata *nd, int mode);
    +extern struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
    + struct opendata *od, unsigned flags,
    + umode_t mode);
    extern int ceph_release(struct inode *inode, struct file *filp);

    /* dir.c */
    --
    1.7.7


    \
     
     \ /
      Last update: 2012-03-28 22:27    [W:0.050 / U:30.592 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site