make finish_no_open() return int
[deliverable/linux.git] / fs / ceph / dir.c
index 3e8094be4604a481999e2921fb0942441c9086a7..d42eee1c5de3842bbd8e69d12a6d8bb1bcb75147 100644 (file)
@@ -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, 1);
-       }
-
        /* can we conclude ENOENT locally? */
        if (dentry->d_inode == NULL) {
                struct ceph_inode_info *ci = ceph_inode(dir);
@@ -642,6 +634,44 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        return dentry;
 }
 
+int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
+{
+       int err;
+       struct dentry *res = NULL;
+
+       if (!(flags & O_CREAT)) {
+               if (dentry->d_name.len > NAME_MAX)
+                       return -ENAMETOOLONG;
+
+               err = ceph_init_dentry(dentry);
+               if (err < 0)
+                       return err;
+
+               return ceph_lookup_open(dir, dentry, file, flags, mode, opened);
+       }
+
+       if (d_unhashed(dentry)) {
+               res = ceph_lookup(dir, dentry, NULL);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       dentry = res;
+       }
+
+       /* We don't deal with positive dentries here */
+       if (dentry->d_inode)
+               return finish_no_open(file, res);
+
+       *opened |= FILE_CREATED;
+       err = ceph_lookup_open(dir, dentry, file, flags, mode, opened);
+       dput(res);
+
+       return err;
+}
+
 /*
  * 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 +732,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, 0);
-               /* 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 +1371,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 = {
This page took 0.027109 seconds and 5 git commands to generate.