aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/dir.c77
-rw-r--r--fs/ceph/file.c26
-rw-r--r--fs/ceph/super.c2
-rw-r--r--fs/ceph/super.h6
4 files changed, 61 insertions, 50 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 6a66bd2d4da0..f391f1e75414 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -575,7 +575,7 @@ static int is_root_ceph_dentry(struct inode *inode, struct dentry *dentry)
575 * the MDS so that it gets our 'caps wanted' value in a single op. 575 * the MDS so that it gets our 'caps wanted' value in a single op.
576 */ 576 */
577static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, 577static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
578 struct nameidata *nd) 578 unsigned int flags)
579{ 579{
580 struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); 580 struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
581 struct ceph_mds_client *mdsc = fsc->mdsc; 581 struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -593,14 +593,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
593 if (err < 0) 593 if (err < 0)
594 return ERR_PTR(err); 594 return ERR_PTR(err);
595 595
596 /* open (but not create!) intent? */
597 if (nd &&
598 (nd->flags & LOOKUP_OPEN) &&
599 !(nd->intent.open.flags & O_CREAT)) {
600 int mode = nd->intent.open.create_mode & ~current->fs->umask;
601 return ceph_lookup_open(dir, dentry, nd, mode, 1);
602 }
603
604 /* can we conclude ENOENT locally? */ 596 /* can we conclude ENOENT locally? */
605 if (dentry->d_inode == NULL) { 597 if (dentry->d_inode == NULL) {
606 struct ceph_inode_info *ci = ceph_inode(dir); 598 struct ceph_inode_info *ci = ceph_inode(dir);
@@ -641,13 +633,51 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
641 return dentry; 633 return dentry;
642} 634}
643 635
636int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
637 struct file *file, unsigned flags, umode_t mode,
638 int *opened)
639{
640 int err;
641 struct dentry *res = NULL;
642
643 if (!(flags & O_CREAT)) {
644 if (dentry->d_name.len > NAME_MAX)
645 return -ENAMETOOLONG;
646
647 err = ceph_init_dentry(dentry);
648 if (err < 0)
649 return err;
650
651 return ceph_lookup_open(dir, dentry, file, flags, mode, opened);
652 }
653
654 if (d_unhashed(dentry)) {
655 res = ceph_lookup(dir, dentry, 0);
656 if (IS_ERR(res))
657 return PTR_ERR(res);
658
659 if (res)
660 dentry = res;
661 }
662
663 /* We don't deal with positive dentries here */
664 if (dentry->d_inode)
665 return finish_no_open(file, res);
666
667 *opened |= FILE_CREATED;
668 err = ceph_lookup_open(dir, dentry, file, flags, mode, opened);
669 dput(res);
670
671 return err;
672}
673
644/* 674/*
645 * If we do a create but get no trace back from the MDS, follow up with 675 * If we do a create but get no trace back from the MDS, follow up with
646 * a lookup (the VFS expects us to link up the provided dentry). 676 * a lookup (the VFS expects us to link up the provided dentry).
647 */ 677 */
648int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) 678int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry)
649{ 679{
650 struct dentry *result = ceph_lookup(dir, dentry, NULL); 680 struct dentry *result = ceph_lookup(dir, dentry, 0);
651 681
652 if (result && !IS_ERR(result)) { 682 if (result && !IS_ERR(result)) {
653 /* 683 /*
@@ -699,25 +729,9 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
699} 729}
700 730
701static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode, 731static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode,
702 struct nameidata *nd) 732 bool excl)
703{ 733{
704 dout("create in dir %p dentry %p name '%.*s'\n", 734 return ceph_mknod(dir, dentry, mode, 0);
705 dir, dentry, dentry->d_name.len, dentry->d_name.name);
706
707 if (ceph_snap(dir) != CEPH_NOSNAP)
708 return -EROFS;
709
710 if (nd) {
711 BUG_ON((nd->flags & LOOKUP_OPEN) == 0);
712 dentry = ceph_lookup_open(dir, dentry, nd, mode, 0);
713 /* hrm, what should i do here if we get aliased? */
714 if (IS_ERR(dentry))
715 return PTR_ERR(dentry);
716 return 0;
717 }
718
719 /* fall back to mknod */
720 return ceph_mknod(dir, dentry, (mode & ~S_IFMT) | S_IFREG, 0);
721} 735}
722 736
723static int ceph_symlink(struct inode *dir, struct dentry *dentry, 737static int ceph_symlink(struct inode *dir, struct dentry *dentry,
@@ -1027,12 +1041,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
1027/* 1041/*
1028 * Check if cached dentry can be trusted. 1042 * Check if cached dentry can be trusted.
1029 */ 1043 */
1030static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) 1044static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
1031{ 1045{
1032 int valid = 0; 1046 int valid = 0;
1033 struct inode *dir; 1047 struct inode *dir;
1034 1048
1035 if (nd && nd->flags & LOOKUP_RCU) 1049 if (flags & LOOKUP_RCU)
1036 return -ECHILD; 1050 return -ECHILD;
1037 1051
1038 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, 1052 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
@@ -1079,7 +1093,7 @@ static void ceph_d_release(struct dentry *dentry)
1079} 1093}
1080 1094
1081static int ceph_snapdir_d_revalidate(struct dentry *dentry, 1095static int ceph_snapdir_d_revalidate(struct dentry *dentry,
1082 struct nameidata *nd) 1096 unsigned int flags)
1083{ 1097{
1084 /* 1098 /*
1085 * Eventually, we'll want to revalidate snapped metadata 1099 * Eventually, we'll want to revalidate snapped metadata
@@ -1356,6 +1370,7 @@ const struct inode_operations ceph_dir_iops = {
1356 .rmdir = ceph_unlink, 1370 .rmdir = ceph_unlink,
1357 .rename = ceph_rename, 1371 .rename = ceph_rename,
1358 .create = ceph_create, 1372 .create = ceph_create,
1373 .atomic_open = ceph_atomic_open,
1359}; 1374};
1360 1375
1361const struct dentry_operations ceph_dentry_ops = { 1376const struct dentry_operations ceph_dentry_ops = {
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 988d4f302e48..1b81d6c31878 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -213,22 +213,15 @@ out:
213 * may_open() fails, the struct *file gets cleaned up (i.e. 213 * may_open() fails, the struct *file gets cleaned up (i.e.
214 * ceph_release gets called). So fear not! 214 * ceph_release gets called). So fear not!
215 */ 215 */
216/* 216int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
217 * flags 217 struct file *file, unsigned flags, umode_t mode,
218 * path_lookup_open -> LOOKUP_OPEN 218 int *opened)
219 * path_lookup_create -> LOOKUP_OPEN|LOOKUP_CREATE
220 */
221struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
222 struct nameidata *nd, int mode,
223 int locked_dir)
224{ 219{
225 struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); 220 struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
226 struct ceph_mds_client *mdsc = fsc->mdsc; 221 struct ceph_mds_client *mdsc = fsc->mdsc;
227 struct file *file;
228 struct ceph_mds_request *req; 222 struct ceph_mds_request *req;
229 struct dentry *ret; 223 struct dentry *ret;
230 int err; 224 int err;
231 int flags = nd->intent.open.flags;
232 225
233 dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", 226 dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n",
234 dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); 227 dentry, dentry->d_name.len, dentry->d_name.name, flags, mode);
@@ -236,7 +229,7 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
236 /* do the open */ 229 /* do the open */
237 req = prepare_open_request(dir->i_sb, flags, mode); 230 req = prepare_open_request(dir->i_sb, flags, mode);
238 if (IS_ERR(req)) 231 if (IS_ERR(req))
239 return ERR_CAST(req); 232 return PTR_ERR(req);
240 req->r_dentry = dget(dentry); 233 req->r_dentry = dget(dentry);
241 req->r_num_caps = 2; 234 req->r_num_caps = 2;
242 if (flags & O_CREAT) { 235 if (flags & O_CREAT) {
@@ -254,14 +247,17 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
254 err = ceph_handle_notrace_create(dir, dentry); 247 err = ceph_handle_notrace_create(dir, dentry);
255 if (err) 248 if (err)
256 goto out; 249 goto out;
257 file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open); 250 err = finish_open(file, req->r_dentry, ceph_open, opened);
258 if (IS_ERR(file))
259 err = PTR_ERR(file);
260out: 251out:
261 ret = ceph_finish_lookup(req, dentry, err); 252 ret = ceph_finish_lookup(req, dentry, err);
262 ceph_mdsc_put_request(req); 253 ceph_mdsc_put_request(req);
263 dout("ceph_lookup_open result=%p\n", ret); 254 dout("ceph_lookup_open result=%p\n", ret);
264 return ret; 255
256 if (IS_ERR(ret))
257 return PTR_ERR(ret);
258
259 dput(ret);
260 return err;
265} 261}
266 262
267int ceph_release(struct inode *inode, struct file *file) 263int ceph_release(struct inode *inode, struct file *file)
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 2c47ecfe4373..b982239f38f9 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -872,7 +872,7 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
872 872
873 if (ceph_test_opt(fsc->client, NOSHARE)) 873 if (ceph_test_opt(fsc->client, NOSHARE))
874 compare_super = NULL; 874 compare_super = NULL;
875 sb = sget(fs_type, compare_super, ceph_set_super, fsc); 875 sb = sget(fs_type, compare_super, ceph_set_super, flags, fsc);
876 if (IS_ERR(sb)) { 876 if (IS_ERR(sb)) {
877 res = ERR_CAST(sb); 877 res = ERR_CAST(sb);
878 goto out; 878 goto out;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 3ea48b7b98b3..ebc95cc652be 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages,
806 loff_t off, size_t len); 806 loff_t off, size_t len);
807extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); 807extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
808extern int ceph_open(struct inode *inode, struct file *file); 808extern int ceph_open(struct inode *inode, struct file *file);
809extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, 809extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
810 struct nameidata *nd, int mode, 810 struct file *od, unsigned flags,
811 int locked_dir); 811 umode_t mode, int *opened);
812extern int ceph_release(struct inode *inode, struct file *filp); 812extern int ceph_release(struct inode *inode, struct file *filp);
813 813
814/* dir.c */ 814/* dir.c */