diff options
Diffstat (limited to 'fs/9p')
-rw-r--r-- | fs/9p/v9fs.h | 4 | ||||
-rw-r--r-- | fs/9p/v9fs_vfs.h | 10 | ||||
-rw-r--r-- | fs/9p/vfs_dentry.c | 34 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 29 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 27 |
5 files changed, 104 insertions, 0 deletions
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 71cab8e3a570..cfdc05527f89 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -116,12 +116,16 @@ struct v9fs_session_info { | |||
116 | struct p9_fid *root_fid; /* Used for file system sync */ | 116 | struct p9_fid *root_fid; /* Used for file system sync */ |
117 | }; | 117 | }; |
118 | 118 | ||
119 | /* cache_validity flags */ | ||
120 | #define V9FS_INO_INVALID_ATTR 0x01 | ||
121 | |||
119 | struct v9fs_inode { | 122 | struct v9fs_inode { |
120 | #ifdef CONFIG_9P_FSCACHE | 123 | #ifdef CONFIG_9P_FSCACHE |
121 | spinlock_t fscache_lock; | 124 | spinlock_t fscache_lock; |
122 | struct fscache_cookie *fscache; | 125 | struct fscache_cookie *fscache; |
123 | struct p9_qid *fscache_key; | 126 | struct p9_qid *fscache_key; |
124 | #endif | 127 | #endif |
128 | unsigned int cache_validity; | ||
125 | struct p9_fid *writeback_fid; | 129 | struct p9_fid *writeback_fid; |
126 | struct inode vfs_inode; | 130 | struct inode vfs_inode; |
127 | }; | 131 | }; |
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index ed9fd00566f2..591807f20188 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -70,4 +70,14 @@ int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); | |||
70 | int v9fs_file_fsync_dotl(struct file *filp, int datasync); | 70 | int v9fs_file_fsync_dotl(struct file *filp, int datasync); |
71 | ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, | 71 | ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, |
72 | const char __user *, size_t, loff_t *, int); | 72 | const char __user *, size_t, loff_t *, int); |
73 | int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); | ||
74 | int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); | ||
75 | static inline void v9fs_invalidate_inode_attr(struct inode *inode) | ||
76 | { | ||
77 | struct v9fs_inode *v9inode; | ||
78 | v9inode = V9FS_I(inode); | ||
79 | v9inode->cache_validity |= V9FS_INO_INVALID_ATTR; | ||
80 | return; | ||
81 | } | ||
82 | |||
73 | #define P9_LOCK_TIMEOUT (30*HZ) | 83 | #define P9_LOCK_TIMEOUT (30*HZ) |
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index a4ae4be5ab59..b6a3b9f7fe4d 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
@@ -100,7 +100,41 @@ static void v9fs_dentry_release(struct dentry *dentry) | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
104 | { | ||
105 | struct p9_fid *fid; | ||
106 | struct inode *inode; | ||
107 | struct v9fs_inode *v9inode; | ||
108 | |||
109 | if (nd->flags & LOOKUP_RCU) | ||
110 | return -ECHILD; | ||
111 | |||
112 | inode = dentry->d_inode; | ||
113 | if (!inode) | ||
114 | goto out_valid; | ||
115 | |||
116 | v9inode = V9FS_I(inode); | ||
117 | if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { | ||
118 | int retval; | ||
119 | struct v9fs_session_info *v9ses; | ||
120 | fid = v9fs_fid_lookup(dentry); | ||
121 | if (IS_ERR(fid)) | ||
122 | return PTR_ERR(fid); | ||
123 | |||
124 | v9ses = v9fs_inode2v9ses(inode); | ||
125 | if (v9fs_proto_dotl(v9ses)) | ||
126 | retval = v9fs_refresh_inode_dotl(fid, inode); | ||
127 | else | ||
128 | retval = v9fs_refresh_inode(fid, inode); | ||
129 | if (retval <= 0) | ||
130 | return retval; | ||
131 | } | ||
132 | out_valid: | ||
133 | return 1; | ||
134 | } | ||
135 | |||
103 | const struct dentry_operations v9fs_cached_dentry_operations = { | 136 | const struct dentry_operations v9fs_cached_dentry_operations = { |
137 | .d_revalidate = v9fs_lookup_revalidate, | ||
104 | .d_delete = v9fs_cached_dentry_delete, | 138 | .d_delete = v9fs_cached_dentry_delete, |
105 | .d_release = v9fs_dentry_release, | 139 | .d_release = v9fs_dentry_release, |
106 | }; | 140 | }; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 334ad12a7bbe..a28fe9fa20a4 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -220,6 +220,7 @@ struct inode *v9fs_alloc_inode(struct super_block *sb) | |||
220 | spin_lock_init(&v9inode->fscache_lock); | 220 | spin_lock_init(&v9inode->fscache_lock); |
221 | #endif | 221 | #endif |
222 | v9inode->writeback_fid = NULL; | 222 | v9inode->writeback_fid = NULL; |
223 | v9inode->cache_validity = 0; | ||
223 | return &v9inode->vfs_inode; | 224 | return &v9inode->vfs_inode; |
224 | } | 225 | } |
225 | 226 | ||
@@ -1010,6 +1011,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
1010 | char tag_name[14]; | 1011 | char tag_name[14]; |
1011 | unsigned int i_nlink; | 1012 | unsigned int i_nlink; |
1012 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 1013 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
1014 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
1013 | 1015 | ||
1014 | inode->i_nlink = 1; | 1016 | inode->i_nlink = 1; |
1015 | 1017 | ||
@@ -1069,6 +1071,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
1069 | 1071 | ||
1070 | /* not real number of blocks, but 512 byte ones ... */ | 1072 | /* not real number of blocks, but 512 byte ones ... */ |
1071 | inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; | 1073 | inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; |
1074 | v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; | ||
1072 | } | 1075 | } |
1073 | 1076 | ||
1074 | /** | 1077 | /** |
@@ -1323,6 +1326,32 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1323 | return retval; | 1326 | return retval; |
1324 | } | 1327 | } |
1325 | 1328 | ||
1329 | int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) | ||
1330 | { | ||
1331 | loff_t i_size; | ||
1332 | struct p9_wstat *st; | ||
1333 | struct v9fs_session_info *v9ses; | ||
1334 | |||
1335 | v9ses = v9fs_inode2v9ses(inode); | ||
1336 | st = p9_client_stat(fid); | ||
1337 | if (IS_ERR(st)) | ||
1338 | return PTR_ERR(st); | ||
1339 | |||
1340 | spin_lock(&inode->i_lock); | ||
1341 | /* | ||
1342 | * We don't want to refresh inode->i_size, | ||
1343 | * because we may have cached data | ||
1344 | */ | ||
1345 | i_size = inode->i_size; | ||
1346 | v9fs_stat2inode(st, inode, inode->i_sb); | ||
1347 | if (v9ses->cache) | ||
1348 | inode->i_size = i_size; | ||
1349 | spin_unlock(&inode->i_lock); | ||
1350 | p9stat_free(st); | ||
1351 | kfree(st); | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1326 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 1355 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { |
1327 | .create = v9fs_vfs_create, | 1356 | .create = v9fs_vfs_create, |
1328 | .lookup = v9fs_vfs_lookup, | 1357 | .lookup = v9fs_vfs_lookup, |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index c6d9677dcb6e..5c04d66afb1d 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -484,6 +484,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) | |||
484 | void | 484 | void |
485 | v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | 485 | v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) |
486 | { | 486 | { |
487 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
487 | 488 | ||
488 | if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { | 489 | if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { |
489 | inode->i_atime.tv_sec = stat->st_atime_sec; | 490 | inode->i_atime.tv_sec = stat->st_atime_sec; |
@@ -542,6 +543,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | |||
542 | /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION | 543 | /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION |
543 | * because the inode structure does not have fields for them. | 544 | * because the inode structure does not have fields for them. |
544 | */ | 545 | */ |
546 | v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; | ||
545 | } | 547 | } |
546 | 548 | ||
547 | static int | 549 | static int |
@@ -822,6 +824,31 @@ ndset: | |||
822 | return NULL; | 824 | return NULL; |
823 | } | 825 | } |
824 | 826 | ||
827 | int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) | ||
828 | { | ||
829 | loff_t i_size; | ||
830 | struct p9_stat_dotl *st; | ||
831 | struct v9fs_session_info *v9ses; | ||
832 | |||
833 | v9ses = v9fs_inode2v9ses(inode); | ||
834 | st = p9_client_getattr_dotl(fid, P9_STATS_ALL); | ||
835 | if (IS_ERR(st)) | ||
836 | return PTR_ERR(st); | ||
837 | |||
838 | spin_lock(&inode->i_lock); | ||
839 | /* | ||
840 | * We don't want to refresh inode->i_size, | ||
841 | * because we may have cached data | ||
842 | */ | ||
843 | i_size = inode->i_size; | ||
844 | v9fs_stat2inode_dotl(st, inode); | ||
845 | if (v9ses->cache) | ||
846 | inode->i_size = i_size; | ||
847 | spin_unlock(&inode->i_lock); | ||
848 | kfree(st); | ||
849 | return 0; | ||
850 | } | ||
851 | |||
825 | const struct inode_operations v9fs_dir_inode_operations_dotl = { | 852 | const struct inode_operations v9fs_dir_inode_operations_dotl = { |
826 | .create = v9fs_vfs_create_dotl, | 853 | .create = v9fs_vfs_create_dotl, |
827 | .lookup = v9fs_vfs_lookup, | 854 | .lookup = v9fs_vfs_lookup, |