diff options
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/dir.c | 77 | ||||
-rw-r--r-- | fs/ceph/file.c | 26 | ||||
-rw-r--r-- | fs/ceph/super.c | 2 | ||||
-rw-r--r-- | fs/ceph/super.h | 6 |
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 | */ |
577 | static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | 577 | static 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 | ||
636 | int 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 | */ |
648 | int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) | 678 | int 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 | ||
701 | static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 731 | static 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 | ||
723 | static int ceph_symlink(struct inode *dir, struct dentry *dentry, | 737 | static 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 | */ |
1030 | static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 1044 | static 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 | ||
1081 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, | 1095 | static 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 | ||
1361 | const struct dentry_operations ceph_dentry_ops = { | 1376 | const 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 | /* | 216 | int 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 | */ | ||
221 | struct 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); | ||
260 | out: | 251 | out: |
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 | ||
267 | int ceph_release(struct inode *inode, struct file *file) | 263 | int 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); |
807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); | 807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); |
808 | extern int ceph_open(struct inode *inode, struct file *file); | 808 | extern int ceph_open(struct inode *inode, struct file *file); |
809 | extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | 809 | extern 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); |
812 | extern int ceph_release(struct inode *inode, struct file *filp); | 812 | extern int ceph_release(struct inode *inode, struct file *filp); |
813 | 813 | ||
814 | /* dir.c */ | 814 | /* dir.c */ |