diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 170 |
1 files changed, 99 insertions, 71 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 57ccb7537dae..cbf9dbb1b2a2 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -712,88 +712,34 @@ error: | |||
712 | } | 712 | } |
713 | 713 | ||
714 | /** | 714 | /** |
715 | * v9fs_vfs_create - VFS hook to create files | 715 | * v9fs_vfs_create - VFS hook to create a regular file |
716 | * | ||
717 | * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called | ||
718 | * for mknod(2). | ||
719 | * | ||
716 | * @dir: directory inode that is being created | 720 | * @dir: directory inode that is being created |
717 | * @dentry: dentry that is being deleted | 721 | * @dentry: dentry that is being deleted |
718 | * @mode: create permissions | 722 | * @mode: create permissions |
719 | * @nd: path information | ||
720 | * | 723 | * |
721 | */ | 724 | */ |
722 | 725 | ||
723 | static int | 726 | static int |
724 | v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 727 | v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
725 | struct nameidata *nd) | 728 | bool excl) |
726 | { | 729 | { |
727 | int err; | 730 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
728 | u32 perm; | 731 | u32 perm = unixmode2p9mode(v9ses, mode); |
729 | int flags; | 732 | struct p9_fid *fid; |
730 | struct file *filp; | ||
731 | struct v9fs_inode *v9inode; | ||
732 | struct v9fs_session_info *v9ses; | ||
733 | struct p9_fid *fid, *inode_fid; | ||
734 | |||
735 | err = 0; | ||
736 | fid = NULL; | ||
737 | v9ses = v9fs_inode2v9ses(dir); | ||
738 | perm = unixmode2p9mode(v9ses, mode); | ||
739 | if (nd) | ||
740 | flags = nd->intent.open.flags; | ||
741 | else | ||
742 | flags = O_RDWR; | ||
743 | 733 | ||
744 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, | 734 | /* P9_OEXCL? */ |
745 | v9fs_uflags2omode(flags, | 735 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR); |
746 | v9fs_proto_dotu(v9ses))); | 736 | if (IS_ERR(fid)) |
747 | if (IS_ERR(fid)) { | 737 | return PTR_ERR(fid); |
748 | err = PTR_ERR(fid); | ||
749 | fid = NULL; | ||
750 | goto error; | ||
751 | } | ||
752 | 738 | ||
753 | v9fs_invalidate_inode_attr(dir); | 739 | v9fs_invalidate_inode_attr(dir); |
754 | /* if we are opening a file, assign the open fid to the file */ | 740 | p9_client_clunk(fid); |
755 | if (nd) { | ||
756 | v9inode = V9FS_I(dentry->d_inode); | ||
757 | mutex_lock(&v9inode->v_mutex); | ||
758 | if (v9ses->cache && !v9inode->writeback_fid && | ||
759 | ((flags & O_ACCMODE) != O_RDONLY)) { | ||
760 | /* | ||
761 | * clone a fid and add it to writeback_fid | ||
762 | * we do it during open time instead of | ||
763 | * page dirty time via write_begin/page_mkwrite | ||
764 | * because we want write after unlink usecase | ||
765 | * to work. | ||
766 | */ | ||
767 | inode_fid = v9fs_writeback_fid(dentry); | ||
768 | if (IS_ERR(inode_fid)) { | ||
769 | err = PTR_ERR(inode_fid); | ||
770 | mutex_unlock(&v9inode->v_mutex); | ||
771 | goto error; | ||
772 | } | ||
773 | v9inode->writeback_fid = (void *) inode_fid; | ||
774 | } | ||
775 | mutex_unlock(&v9inode->v_mutex); | ||
776 | filp = lookup_instantiate_filp(nd, dentry, generic_file_open); | ||
777 | if (IS_ERR(filp)) { | ||
778 | err = PTR_ERR(filp); | ||
779 | goto error; | ||
780 | } | ||
781 | |||
782 | filp->private_data = fid; | ||
783 | #ifdef CONFIG_9P_FSCACHE | ||
784 | if (v9ses->cache) | ||
785 | v9fs_cache_inode_set_cookie(dentry->d_inode, filp); | ||
786 | #endif | ||
787 | } else | ||
788 | p9_client_clunk(fid); | ||
789 | 741 | ||
790 | return 0; | 742 | return 0; |
791 | |||
792 | error: | ||
793 | if (fid) | ||
794 | p9_client_clunk(fid); | ||
795 | |||
796 | return err; | ||
797 | } | 743 | } |
798 | 744 | ||
799 | /** | 745 | /** |
@@ -839,7 +785,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode | |||
839 | */ | 785 | */ |
840 | 786 | ||
841 | struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | 787 | struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, |
842 | struct nameidata *nameidata) | 788 | unsigned int flags) |
843 | { | 789 | { |
844 | struct dentry *res; | 790 | struct dentry *res; |
845 | struct super_block *sb; | 791 | struct super_block *sb; |
@@ -849,8 +795,8 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
849 | char *name; | 795 | char *name; |
850 | int result = 0; | 796 | int result = 0; |
851 | 797 | ||
852 | p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", | 798 | p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n", |
853 | dir, dentry->d_name.name, dentry, nameidata); | 799 | dir, dentry->d_name.name, dentry, flags); |
854 | 800 | ||
855 | if (dentry->d_name.len > NAME_MAX) | 801 | if (dentry->d_name.len > NAME_MAX) |
856 | return ERR_PTR(-ENAMETOOLONG); | 802 | return ERR_PTR(-ENAMETOOLONG); |
@@ -910,6 +856,86 @@ error: | |||
910 | return ERR_PTR(result); | 856 | return ERR_PTR(result); |
911 | } | 857 | } |
912 | 858 | ||
859 | static int | ||
860 | v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | ||
861 | struct file *file, unsigned flags, umode_t mode, | ||
862 | int *opened) | ||
863 | { | ||
864 | int err; | ||
865 | u32 perm; | ||
866 | struct v9fs_inode *v9inode; | ||
867 | struct v9fs_session_info *v9ses; | ||
868 | struct p9_fid *fid, *inode_fid; | ||
869 | struct dentry *res = NULL; | ||
870 | |||
871 | if (d_unhashed(dentry)) { | ||
872 | res = v9fs_vfs_lookup(dir, dentry, 0); | ||
873 | if (IS_ERR(res)) | ||
874 | return PTR_ERR(res); | ||
875 | |||
876 | if (res) | ||
877 | dentry = res; | ||
878 | } | ||
879 | |||
880 | /* Only creates */ | ||
881 | if (!(flags & O_CREAT) || dentry->d_inode) | ||
882 | return finish_no_open(file, res); | ||
883 | |||
884 | err = 0; | ||
885 | fid = NULL; | ||
886 | v9ses = v9fs_inode2v9ses(dir); | ||
887 | perm = unixmode2p9mode(v9ses, mode); | ||
888 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, | ||
889 | v9fs_uflags2omode(flags, | ||
890 | v9fs_proto_dotu(v9ses))); | ||
891 | if (IS_ERR(fid)) { | ||
892 | err = PTR_ERR(fid); | ||
893 | fid = NULL; | ||
894 | goto error; | ||
895 | } | ||
896 | |||
897 | v9fs_invalidate_inode_attr(dir); | ||
898 | v9inode = V9FS_I(dentry->d_inode); | ||
899 | mutex_lock(&v9inode->v_mutex); | ||
900 | if (v9ses->cache && !v9inode->writeback_fid && | ||
901 | ((flags & O_ACCMODE) != O_RDONLY)) { | ||
902 | /* | ||
903 | * clone a fid and add it to writeback_fid | ||
904 | * we do it during open time instead of | ||
905 | * page dirty time via write_begin/page_mkwrite | ||
906 | * because we want write after unlink usecase | ||
907 | * to work. | ||
908 | */ | ||
909 | inode_fid = v9fs_writeback_fid(dentry); | ||
910 | if (IS_ERR(inode_fid)) { | ||
911 | err = PTR_ERR(inode_fid); | ||
912 | mutex_unlock(&v9inode->v_mutex); | ||
913 | goto error; | ||
914 | } | ||
915 | v9inode->writeback_fid = (void *) inode_fid; | ||
916 | } | ||
917 | mutex_unlock(&v9inode->v_mutex); | ||
918 | err = finish_open(file, dentry, generic_file_open, opened); | ||
919 | if (err) | ||
920 | goto error; | ||
921 | |||
922 | file->private_data = fid; | ||
923 | #ifdef CONFIG_9P_FSCACHE | ||
924 | if (v9ses->cache) | ||
925 | v9fs_cache_inode_set_cookie(dentry->d_inode, file); | ||
926 | #endif | ||
927 | |||
928 | *opened |= FILE_CREATED; | ||
929 | out: | ||
930 | dput(res); | ||
931 | return err; | ||
932 | |||
933 | error: | ||
934 | if (fid) | ||
935 | p9_client_clunk(fid); | ||
936 | goto out; | ||
937 | } | ||
938 | |||
913 | /** | 939 | /** |
914 | * v9fs_vfs_unlink - VFS unlink hook to delete an inode | 940 | * v9fs_vfs_unlink - VFS unlink hook to delete an inode |
915 | * @i: inode that is being unlinked | 941 | * @i: inode that is being unlinked |
@@ -1488,6 +1514,7 @@ out: | |||
1488 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 1514 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { |
1489 | .create = v9fs_vfs_create, | 1515 | .create = v9fs_vfs_create, |
1490 | .lookup = v9fs_vfs_lookup, | 1516 | .lookup = v9fs_vfs_lookup, |
1517 | .atomic_open = v9fs_vfs_atomic_open, | ||
1491 | .symlink = v9fs_vfs_symlink, | 1518 | .symlink = v9fs_vfs_symlink, |
1492 | .link = v9fs_vfs_link, | 1519 | .link = v9fs_vfs_link, |
1493 | .unlink = v9fs_vfs_unlink, | 1520 | .unlink = v9fs_vfs_unlink, |
@@ -1502,6 +1529,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { | |||
1502 | static const struct inode_operations v9fs_dir_inode_operations = { | 1529 | static const struct inode_operations v9fs_dir_inode_operations = { |
1503 | .create = v9fs_vfs_create, | 1530 | .create = v9fs_vfs_create, |
1504 | .lookup = v9fs_vfs_lookup, | 1531 | .lookup = v9fs_vfs_lookup, |
1532 | .atomic_open = v9fs_vfs_atomic_open, | ||
1505 | .unlink = v9fs_vfs_unlink, | 1533 | .unlink = v9fs_vfs_unlink, |
1506 | .mkdir = v9fs_vfs_mkdir, | 1534 | .mkdir = v9fs_vfs_mkdir, |
1507 | .rmdir = v9fs_vfs_rmdir, | 1535 | .rmdir = v9fs_vfs_rmdir, |