aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-06-05 09:10:26 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-14 08:33:17 -0400
commite43ae79c540270865918dab5ac914c74f43101e2 (patch)
treedc580a2de6799cfc3b99a6ab43e16c834e23736a /fs/9p
parent2d83bde9a16e18eafdc73a3a1f4a8eb110e49672 (diff)
9p: implement i_op->atomic_open()
Add an ->atomic_open implementation which replaces the atomic open+create operation implemented via ->create. No functionality is changed. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> CC: Eric Van Hensbergen <ericvh@gmail.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/vfs_inode.c169
-rw-r--r--fs/9p/vfs_inode_dotl.c52
2 files changed, 137 insertions, 84 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 57ccb7537dae..e8c42ceb89ba 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -712,11 +712,14 @@ 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
@@ -724,76 +727,19 @@ static 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 struct nameidata *nd)
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/**
@@ -910,6 +856,93 @@ error:
910 return ERR_PTR(result); 856 return ERR_PTR(result);
911} 857}
912 858
859static struct file *
860v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
861 struct opendata *od, unsigned flags, umode_t mode,
862 bool *created)
863{
864 int err;
865 u32 perm;
866 struct file *filp;
867 struct v9fs_inode *v9inode;
868 struct v9fs_session_info *v9ses;
869 struct p9_fid *fid, *inode_fid;
870 struct dentry *res = NULL;
871
872 if (d_unhashed(dentry)) {
873 res = v9fs_vfs_lookup(dir, dentry, NULL);
874 if (IS_ERR(res))
875 return ERR_CAST(res);
876
877 if (res)
878 dentry = res;
879 }
880
881 /* Only creates */
882 if (!(flags & O_CREAT) || dentry->d_inode) {
883 finish_no_open(od, res);
884 return NULL;
885 }
886
887 err = 0;
888 fid = NULL;
889 v9ses = v9fs_inode2v9ses(dir);
890 perm = unixmode2p9mode(v9ses, mode);
891 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
892 v9fs_uflags2omode(flags,
893 v9fs_proto_dotu(v9ses)));
894 if (IS_ERR(fid)) {
895 err = PTR_ERR(fid);
896 fid = NULL;
897 goto error;
898 }
899
900 v9fs_invalidate_inode_attr(dir);
901 v9inode = V9FS_I(dentry->d_inode);
902 mutex_lock(&v9inode->v_mutex);
903 if (v9ses->cache && !v9inode->writeback_fid &&
904 ((flags & O_ACCMODE) != O_RDONLY)) {
905 /*
906 * clone a fid and add it to writeback_fid
907 * we do it during open time instead of
908 * page dirty time via write_begin/page_mkwrite
909 * because we want write after unlink usecase
910 * to work.
911 */
912 inode_fid = v9fs_writeback_fid(dentry);
913 if (IS_ERR(inode_fid)) {
914 err = PTR_ERR(inode_fid);
915 mutex_unlock(&v9inode->v_mutex);
916 goto error;
917 }
918 v9inode->writeback_fid = (void *) inode_fid;
919 }
920 mutex_unlock(&v9inode->v_mutex);
921 filp = finish_open(od, dentry, generic_file_open);
922 if (IS_ERR(filp)) {
923 err = PTR_ERR(filp);
924 goto error;
925 }
926
927 filp->private_data = fid;
928#ifdef CONFIG_9P_FSCACHE
929 if (v9ses->cache)
930 v9fs_cache_inode_set_cookie(dentry->d_inode, filp);
931#endif
932
933 *created = true;
934out:
935 dput(res);
936 return filp;
937
938error:
939 if (fid)
940 p9_client_clunk(fid);
941
942 filp = ERR_PTR(err);
943 goto out;
944}
945
913/** 946/**
914 * v9fs_vfs_unlink - VFS unlink hook to delete an inode 947 * v9fs_vfs_unlink - VFS unlink hook to delete an inode
915 * @i: inode that is being unlinked 948 * @i: inode that is being unlinked
@@ -1488,6 +1521,7 @@ out:
1488static const struct inode_operations v9fs_dir_inode_operations_dotu = { 1521static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1489 .create = v9fs_vfs_create, 1522 .create = v9fs_vfs_create,
1490 .lookup = v9fs_vfs_lookup, 1523 .lookup = v9fs_vfs_lookup,
1524 .atomic_open = v9fs_vfs_atomic_open,
1491 .symlink = v9fs_vfs_symlink, 1525 .symlink = v9fs_vfs_symlink,
1492 .link = v9fs_vfs_link, 1526 .link = v9fs_vfs_link,
1493 .unlink = v9fs_vfs_unlink, 1527 .unlink = v9fs_vfs_unlink,
@@ -1502,6 +1536,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1502static const struct inode_operations v9fs_dir_inode_operations = { 1536static const struct inode_operations v9fs_dir_inode_operations = {
1503 .create = v9fs_vfs_create, 1537 .create = v9fs_vfs_create,
1504 .lookup = v9fs_vfs_lookup, 1538 .lookup = v9fs_vfs_lookup,
1539 .atomic_open = v9fs_vfs_atomic_open,
1505 .unlink = v9fs_vfs_unlink, 1540 .unlink = v9fs_vfs_unlink,
1506 .mkdir = v9fs_vfs_mkdir, 1541 .mkdir = v9fs_vfs_mkdir,
1507 .rmdir = v9fs_vfs_rmdir, 1542 .rmdir = v9fs_vfs_rmdir,
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index e3dd2a1e2bfc..a354fe2cb234 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -230,7 +230,6 @@ int v9fs_open_to_dotl_flags(int flags)
230 * @dir: directory inode that is being created 230 * @dir: directory inode that is being created
231 * @dentry: dentry that is being deleted 231 * @dentry: dentry that is being deleted
232 * @mode: create permissions 232 * @mode: create permissions
233 * @nd: path information
234 * 233 *
235 */ 234 */
236 235
@@ -238,9 +237,16 @@ static int
238v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, 237v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
239 struct nameidata *nd) 238 struct nameidata *nd)
240{ 239{
240 return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
241}
242
243static struct file *
244v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
245 struct opendata *od, unsigned flags, umode_t omode,
246 bool *created)
247{
241 int err = 0; 248 int err = 0;
242 gid_t gid; 249 gid_t gid;
243 int flags;
244 umode_t mode; 250 umode_t mode;
245 char *name = NULL; 251 char *name = NULL;
246 struct file *filp; 252 struct file *filp;
@@ -251,19 +257,25 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
251 struct p9_fid *dfid, *ofid, *inode_fid; 257 struct p9_fid *dfid, *ofid, *inode_fid;
252 struct v9fs_session_info *v9ses; 258 struct v9fs_session_info *v9ses;
253 struct posix_acl *pacl = NULL, *dacl = NULL; 259 struct posix_acl *pacl = NULL, *dacl = NULL;
260 struct dentry *res = NULL;
254 261
255 v9ses = v9fs_inode2v9ses(dir); 262 if (d_unhashed(dentry)) {
256 if (nd) 263 res = v9fs_vfs_lookup(dir, dentry, NULL);
257 flags = nd->intent.open.flags; 264 if (IS_ERR(res))
258 else { 265 return ERR_CAST(res);
259 /* 266
260 * create call without LOOKUP_OPEN is due 267 if (res)
261 * to mknod of regular files. So use mknod 268 dentry = res;
262 * operation. 269 }
263 */ 270
264 return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); 271 /* Only creates */
272 if (!(flags & O_CREAT) || dentry->d_inode) {
273 finish_no_open(od, res);
274 return NULL;
265 } 275 }
266 276
277 v9ses = v9fs_inode2v9ses(dir);
278
267 name = (char *) dentry->d_name.name; 279 name = (char *) dentry->d_name.name;
268 p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n", 280 p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n",
269 name, flags, omode); 281 name, flags, omode);
@@ -272,7 +284,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
272 if (IS_ERR(dfid)) { 284 if (IS_ERR(dfid)) {
273 err = PTR_ERR(dfid); 285 err = PTR_ERR(dfid);
274 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 286 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
275 return err; 287 goto err_return;
276 } 288 }
277 289
278 /* clone a fid to use for creation */ 290 /* clone a fid to use for creation */
@@ -280,7 +292,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
280 if (IS_ERR(ofid)) { 292 if (IS_ERR(ofid)) {
281 err = PTR_ERR(ofid); 293 err = PTR_ERR(ofid);
282 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 294 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
283 return err; 295 goto err_return;
284 } 296 }
285 297
286 gid = v9fs_get_fsgid_for_create(dir); 298 gid = v9fs_get_fsgid_for_create(dir);
@@ -345,7 +357,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
345 } 357 }
346 mutex_unlock(&v9inode->v_mutex); 358 mutex_unlock(&v9inode->v_mutex);
347 /* Since we are opening a file, assign the open fid to the file */ 359 /* Since we are opening a file, assign the open fid to the file */
348 filp = lookup_instantiate_filp(nd, dentry, generic_file_open); 360 filp = finish_open(od, dentry, generic_file_open);
349 if (IS_ERR(filp)) { 361 if (IS_ERR(filp)) {
350 err = PTR_ERR(filp); 362 err = PTR_ERR(filp);
351 goto err_clunk_old_fid; 363 goto err_clunk_old_fid;
@@ -355,7 +367,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
355 if (v9ses->cache) 367 if (v9ses->cache)
356 v9fs_cache_inode_set_cookie(inode, filp); 368 v9fs_cache_inode_set_cookie(inode, filp);
357#endif 369#endif
358 return 0; 370 *created = true;
371out:
372 dput(res);
373 return filp;
359 374
360error: 375error:
361 if (fid) 376 if (fid)
@@ -364,7 +379,9 @@ err_clunk_old_fid:
364 if (ofid) 379 if (ofid)
365 p9_client_clunk(ofid); 380 p9_client_clunk(ofid);
366 v9fs_set_create_acl(NULL, &dacl, &pacl); 381 v9fs_set_create_acl(NULL, &dacl, &pacl);
367 return err; 382err_return:
383 filp = ERR_PTR(err);
384 goto out;
368} 385}
369 386
370/** 387/**
@@ -982,6 +999,7 @@ out:
982 999
983const struct inode_operations v9fs_dir_inode_operations_dotl = { 1000const struct inode_operations v9fs_dir_inode_operations_dotl = {
984 .create = v9fs_vfs_create_dotl, 1001 .create = v9fs_vfs_create_dotl,
1002 .atomic_open = v9fs_vfs_atomic_open_dotl,
985 .lookup = v9fs_vfs_lookup, 1003 .lookup = v9fs_vfs_lookup,
986 .link = v9fs_vfs_link_dotl, 1004 .link = v9fs_vfs_link_dotl,
987 .symlink = v9fs_vfs_symlink_dotl, 1005 .symlink = v9fs_vfs_symlink_dotl,