aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/9p/v9fs.h4
-rw-r--r--fs/9p/v9fs_vfs.h10
-rw-r--r--fs/9p/vfs_dentry.c34
-rw-r--r--fs/9p/vfs_inode.c29
-rw-r--r--fs/9p/vfs_inode_dotl.c27
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
119struct v9fs_inode { 122struct 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 *);
70int v9fs_file_fsync_dotl(struct file *filp, int datasync); 70int v9fs_file_fsync_dotl(struct file *filp, int datasync);
71ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, 71ssize_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);
73int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode);
74int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode);
75static 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
103static 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 }
132out_valid:
133 return 1;
134}
135
103const struct dentry_operations v9fs_cached_dentry_operations = { 136const 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
1329int 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
1326static const struct inode_operations v9fs_dir_inode_operations_dotu = { 1355static 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)
484void 484void
485v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) 485v9fs_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
547static int 549static int
@@ -822,6 +824,31 @@ ndset:
822 return NULL; 824 return NULL;
823} 825}
824 826
827int 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
825const struct inode_operations v9fs_dir_inode_operations_dotl = { 852const 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,