aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-23 15:27:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-23 15:27:27 -0400
commita66d2c8f7ec1284206ca7c14569e2a607583f1e3 (patch)
tree08cf68bcef3559b370843cab8191e5cc0f740bde /fs/9p/vfs_inode.c
parenta6be1fcbc57f95bb47ef3c8e4ee3d83731b8f21e (diff)
parent8cae6f7158ec1fa44c8a04a43db7d8020ec60437 (diff)
Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull the big VFS changes from Al Viro: "This one is *big* and changes quite a few things around VFS. What's in there: - the first of two really major architecture changes - death to open intents. The former is finally there; it was very long in making, but with Miklos getting through really hard and messy final push in fs/namei.c, we finally have it. Unlike his variant, this one doesn't introduce struct opendata; what we have instead is ->atomic_open() taking preallocated struct file * and passing everything via its fields. Instead of returning struct file *, it returns -E... on error, 0 on success and 1 in "deal with it yourself" case (e.g. symlink found on server, etc.). See comments before fs/namei.c:atomic_open(). That made a lot of goodies finally possible and quite a few are in that pile: ->lookup(), ->d_revalidate() and ->create() do not get struct nameidata * anymore; ->lookup() and ->d_revalidate() get lookup flags instead, ->create() gets "do we want it exclusive" flag. With the introduction of new helper (kern_path_locked()) we are rid of all struct nameidata instances outside of fs/namei.c; it's still visible in namei.h, but not for long. Come the next cycle, declaration will move either to fs/internal.h or to fs/namei.c itself. [me, miklos, hch] - The second major change: behaviour of final fput(). Now we have __fput() done without any locks held by caller *and* not from deep in call stack. That obviously lifts a lot of constraints on the locking in there. Moreover, it's legal now to call fput() from atomic contexts (which has immediately simplified life for aio.c). We also don't need anti-recursion logics in __scm_destroy() anymore. There is a price, though - the damn thing has become partially asynchronous. For fput() from normal process we are guaranteed that pending __fput() will be done before the caller returns to userland, exits or gets stopped for ptrace. For kernel threads and atomic contexts it's done via schedule_work(), so theoretically we might need a way to make sure it's finished; so far only one such place had been found, but there might be more. There's flush_delayed_fput() (do all pending __fput()) and there's __fput_sync() (fput() analog doing __fput() immediately). I hope we won't need them often; see warnings in fs/file_table.c for details. [me, based on task_work series from Oleg merged last cycle] - sync series from Jan - large part of "death to sync_supers()" work from Artem; the only bits missing here are exofs and ext4 ones. As far as I understand, those are going via the exofs and ext4 trees resp.; once they are in, we can put ->write_super() to the rest, along with the thread calling it. - preparatory bits from unionmount series (from dhowells). - assorted cleanups and fixes all over the place, as usual. This is not the last pile for this cycle; there's at least jlayton's ESTALE work and fsfreeze series (the latter - in dire need of fixes, so I'm not sure it'll make the cut this cycle). I'll probably throw symlink/hardlink restrictions stuff from Kees into the next pile, too. Plus there's a lot of misc patches I hadn't thrown into that one - it's large enough as it is..." * 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (127 commits) ext4: switch EXT4_IOC_RESIZE_FS to mnt_want_write_file() btrfs: switch btrfs_ioctl_balance() to mnt_want_write_file() switch dentry_open() to struct path, make it grab references itself spufs: shift dget/mntget towards dentry_open() zoran: don't bother with struct file * in zoran_map ecryptfs: don't reinvent the wheels, please - use struct completion don't expose I_NEW inodes via dentry->d_inode tidy up namei.c a bit unobfuscate follow_up() a bit ext3: pass custom EOF to generic_file_llseek_size() ext4: use core vfs llseek code for dir seeks vfs: allow custom EOF in generic_file_llseek code vfs: Avoid unnecessary WB_SYNC_NONE writeback during sys_sync and reorder sync passes vfs: Remove unnecessary flushing of block devices vfs: Make sys_sync writeout also block device inodes vfs: Create function for iterating over block devices vfs: Reorder operations during sys_sync quota: Move quota syncing to ->sync_fs method quota: Split dquot_quota_sync() to writeback and cache flushing part vfs: Move noop_backing_dev_info check from sync into writeback ...
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,