diff options
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r-- | fs/ceph/dir.c | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 3e8094be4604..00894ff9246c 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -576,7 +576,7 @@ static int is_root_ceph_dentry(struct inode *inode, struct dentry *dentry) | |||
576 | * the MDS so that it gets our 'caps wanted' value in a single op. | 576 | * the MDS so that it gets our 'caps wanted' value in a single op. |
577 | */ | 577 | */ |
578 | static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | 578 | static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, |
579 | struct nameidata *nd) | 579 | unsigned int flags) |
580 | { | 580 | { |
581 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); | 581 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
582 | struct ceph_mds_client *mdsc = fsc->mdsc; | 582 | struct ceph_mds_client *mdsc = fsc->mdsc; |
@@ -594,14 +594,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
594 | if (err < 0) | 594 | if (err < 0) |
595 | return ERR_PTR(err); | 595 | return ERR_PTR(err); |
596 | 596 | ||
597 | /* open (but not create!) intent? */ | ||
598 | if (nd && | ||
599 | (nd->flags & LOOKUP_OPEN) && | ||
600 | !(nd->intent.open.flags & O_CREAT)) { | ||
601 | int mode = nd->intent.open.create_mode & ~current->fs->umask; | ||
602 | return ceph_lookup_open(dir, dentry, nd, mode, 1); | ||
603 | } | ||
604 | |||
605 | /* can we conclude ENOENT locally? */ | 597 | /* can we conclude ENOENT locally? */ |
606 | if (dentry->d_inode == NULL) { | 598 | if (dentry->d_inode == NULL) { |
607 | struct ceph_inode_info *ci = ceph_inode(dir); | 599 | struct ceph_inode_info *ci = ceph_inode(dir); |
@@ -642,13 +634,51 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
642 | return dentry; | 634 | return dentry; |
643 | } | 635 | } |
644 | 636 | ||
637 | int ceph_atomic_open(struct inode *dir, struct dentry *dentry, | ||
638 | struct file *file, unsigned flags, umode_t mode, | ||
639 | int *opened) | ||
640 | { | ||
641 | int err; | ||
642 | struct dentry *res = NULL; | ||
643 | |||
644 | if (!(flags & O_CREAT)) { | ||
645 | if (dentry->d_name.len > NAME_MAX) | ||
646 | return -ENAMETOOLONG; | ||
647 | |||
648 | err = ceph_init_dentry(dentry); | ||
649 | if (err < 0) | ||
650 | return err; | ||
651 | |||
652 | return ceph_lookup_open(dir, dentry, file, flags, mode, opened); | ||
653 | } | ||
654 | |||
655 | if (d_unhashed(dentry)) { | ||
656 | res = ceph_lookup(dir, dentry, 0); | ||
657 | if (IS_ERR(res)) | ||
658 | return PTR_ERR(res); | ||
659 | |||
660 | if (res) | ||
661 | dentry = res; | ||
662 | } | ||
663 | |||
664 | /* We don't deal with positive dentries here */ | ||
665 | if (dentry->d_inode) | ||
666 | return finish_no_open(file, res); | ||
667 | |||
668 | *opened |= FILE_CREATED; | ||
669 | err = ceph_lookup_open(dir, dentry, file, flags, mode, opened); | ||
670 | dput(res); | ||
671 | |||
672 | return err; | ||
673 | } | ||
674 | |||
645 | /* | 675 | /* |
646 | * If we do a create but get no trace back from the MDS, follow up with | 676 | * If we do a create but get no trace back from the MDS, follow up with |
647 | * a lookup (the VFS expects us to link up the provided dentry). | 677 | * a lookup (the VFS expects us to link up the provided dentry). |
648 | */ | 678 | */ |
649 | int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) | 679 | int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) |
650 | { | 680 | { |
651 | struct dentry *result = ceph_lookup(dir, dentry, NULL); | 681 | struct dentry *result = ceph_lookup(dir, dentry, 0); |
652 | 682 | ||
653 | if (result && !IS_ERR(result)) { | 683 | if (result && !IS_ERR(result)) { |
654 | /* | 684 | /* |
@@ -700,25 +730,9 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, | |||
700 | } | 730 | } |
701 | 731 | ||
702 | static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 732 | static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
703 | struct nameidata *nd) | 733 | bool excl) |
704 | { | 734 | { |
705 | dout("create in dir %p dentry %p name '%.*s'\n", | 735 | return ceph_mknod(dir, dentry, mode, 0); |
706 | dir, dentry, dentry->d_name.len, dentry->d_name.name); | ||
707 | |||
708 | if (ceph_snap(dir) != CEPH_NOSNAP) | ||
709 | return -EROFS; | ||
710 | |||
711 | if (nd) { | ||
712 | BUG_ON((nd->flags & LOOKUP_OPEN) == 0); | ||
713 | dentry = ceph_lookup_open(dir, dentry, nd, mode, 0); | ||
714 | /* hrm, what should i do here if we get aliased? */ | ||
715 | if (IS_ERR(dentry)) | ||
716 | return PTR_ERR(dentry); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | /* fall back to mknod */ | ||
721 | return ceph_mknod(dir, dentry, (mode & ~S_IFMT) | S_IFREG, 0); | ||
722 | } | 736 | } |
723 | 737 | ||
724 | static int ceph_symlink(struct inode *dir, struct dentry *dentry, | 738 | static int ceph_symlink(struct inode *dir, struct dentry *dentry, |
@@ -1028,12 +1042,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry) | |||
1028 | /* | 1042 | /* |
1029 | * Check if cached dentry can be trusted. | 1043 | * Check if cached dentry can be trusted. |
1030 | */ | 1044 | */ |
1031 | static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 1045 | static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags) |
1032 | { | 1046 | { |
1033 | int valid = 0; | 1047 | int valid = 0; |
1034 | struct inode *dir; | 1048 | struct inode *dir; |
1035 | 1049 | ||
1036 | if (nd && nd->flags & LOOKUP_RCU) | 1050 | if (flags & LOOKUP_RCU) |
1037 | return -ECHILD; | 1051 | return -ECHILD; |
1038 | 1052 | ||
1039 | dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, | 1053 | dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, |
@@ -1080,7 +1094,7 @@ static void ceph_d_release(struct dentry *dentry) | |||
1080 | } | 1094 | } |
1081 | 1095 | ||
1082 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, | 1096 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, |
1083 | struct nameidata *nd) | 1097 | unsigned int flags) |
1084 | { | 1098 | { |
1085 | /* | 1099 | /* |
1086 | * Eventually, we'll want to revalidate snapped metadata | 1100 | * Eventually, we'll want to revalidate snapped metadata |
@@ -1357,6 +1371,7 @@ const struct inode_operations ceph_dir_iops = { | |||
1357 | .rmdir = ceph_unlink, | 1371 | .rmdir = ceph_unlink, |
1358 | .rename = ceph_rename, | 1372 | .rename = ceph_rename, |
1359 | .create = ceph_create, | 1373 | .create = ceph_create, |
1374 | .atomic_open = ceph_atomic_open, | ||
1360 | }; | 1375 | }; |
1361 | 1376 | ||
1362 | const struct dentry_operations ceph_dentry_ops = { | 1377 | const struct dentry_operations ceph_dentry_ops = { |