aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c170
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
723static int 726static int
724v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, 727v9fs_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
792error:
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
841struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, 787struct 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
859static int
860v9fs_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;
929out:
930 dput(res);
931 return err;
932
933error:
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:
1488static const struct inode_operations v9fs_dir_inode_operations_dotu = { 1514static 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 = {
1502static const struct inode_operations v9fs_dir_inode_operations = { 1529static 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,