diff options
author | John Muir <muirj@nortel.com> | 2009-05-31 11:13:57 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2009-06-30 14:12:24 -0400 |
commit | 3b463ae0c6264f70e5d4c0a9c46af20fed43c96e (patch) | |
tree | 03c6abdd0671d74452cbd1f6fc6d637363eb6389 /fs/fuse/dev.c | |
parent | e0a43ddcc08c34dbd666d93600fd23914505f4aa (diff) |
fuse: invalidation reverse calls
Add notification messages that allow the filesystem to invalidate VFS
caches.
Two notifications are added:
1) inode invalidation
- invalidate cached attributes
- invalidate a range of pages in the page cache (this is optional)
2) dentry invalidation
- try to invalidate a subtree in the dentry cache
Care must be taken while accessing the 'struct super_block' for the
mount, as it can go away while an invalidation is in progress. To
prevent this, introduce a rw-semaphore, that is taken for read during
the invalidation and taken for write in the ->kill_sb callback.
Cc: Csaba Henk <csaba@gluster.com>
Cc: Anand Avati <avati@zresearch.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r-- | fs/fuse/dev.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8a11a8c67c42..f58ecbc416c8 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -849,6 +849,81 @@ err: | |||
849 | return err; | 849 | return err; |
850 | } | 850 | } |
851 | 851 | ||
852 | static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size, | ||
853 | struct fuse_copy_state *cs) | ||
854 | { | ||
855 | struct fuse_notify_inval_inode_out outarg; | ||
856 | int err = -EINVAL; | ||
857 | |||
858 | if (size != sizeof(outarg)) | ||
859 | goto err; | ||
860 | |||
861 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
862 | if (err) | ||
863 | goto err; | ||
864 | fuse_copy_finish(cs); | ||
865 | |||
866 | down_read(&fc->killsb); | ||
867 | err = -ENOENT; | ||
868 | if (!fc->sb) | ||
869 | goto err_unlock; | ||
870 | |||
871 | err = fuse_reverse_inval_inode(fc->sb, outarg.ino, | ||
872 | outarg.off, outarg.len); | ||
873 | |||
874 | err_unlock: | ||
875 | up_read(&fc->killsb); | ||
876 | return err; | ||
877 | |||
878 | err: | ||
879 | fuse_copy_finish(cs); | ||
880 | return err; | ||
881 | } | ||
882 | |||
883 | static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, | ||
884 | struct fuse_copy_state *cs) | ||
885 | { | ||
886 | struct fuse_notify_inval_entry_out outarg; | ||
887 | int err = -EINVAL; | ||
888 | char buf[FUSE_NAME_MAX+1]; | ||
889 | struct qstr name; | ||
890 | |||
891 | if (size < sizeof(outarg)) | ||
892 | goto err; | ||
893 | |||
894 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
895 | if (err) | ||
896 | goto err; | ||
897 | |||
898 | err = -ENAMETOOLONG; | ||
899 | if (outarg.namelen > FUSE_NAME_MAX) | ||
900 | goto err; | ||
901 | |||
902 | name.name = buf; | ||
903 | name.len = outarg.namelen; | ||
904 | err = fuse_copy_one(cs, buf, outarg.namelen + 1); | ||
905 | if (err) | ||
906 | goto err; | ||
907 | fuse_copy_finish(cs); | ||
908 | buf[outarg.namelen] = 0; | ||
909 | name.hash = full_name_hash(name.name, name.len); | ||
910 | |||
911 | down_read(&fc->killsb); | ||
912 | err = -ENOENT; | ||
913 | if (!fc->sb) | ||
914 | goto err_unlock; | ||
915 | |||
916 | err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name); | ||
917 | |||
918 | err_unlock: | ||
919 | up_read(&fc->killsb); | ||
920 | return err; | ||
921 | |||
922 | err: | ||
923 | fuse_copy_finish(cs); | ||
924 | return err; | ||
925 | } | ||
926 | |||
852 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | 927 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, |
853 | unsigned int size, struct fuse_copy_state *cs) | 928 | unsigned int size, struct fuse_copy_state *cs) |
854 | { | 929 | { |
@@ -856,6 +931,12 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | |||
856 | case FUSE_NOTIFY_POLL: | 931 | case FUSE_NOTIFY_POLL: |
857 | return fuse_notify_poll(fc, size, cs); | 932 | return fuse_notify_poll(fc, size, cs); |
858 | 933 | ||
934 | case FUSE_NOTIFY_INVAL_INODE: | ||
935 | return fuse_notify_inval_inode(fc, size, cs); | ||
936 | |||
937 | case FUSE_NOTIFY_INVAL_ENTRY: | ||
938 | return fuse_notify_inval_entry(fc, size, cs); | ||
939 | |||
859 | default: | 940 | default: |
860 | fuse_copy_finish(cs); | 941 | fuse_copy_finish(cs); |
861 | return -EINVAL; | 942 | return -EINVAL; |