aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-02-28 06:34:06 -0500
committerEric Van Hensbergen <ericvh@gmail.com>2011-03-15 10:57:40 -0400
commitb3cbea03b4edbd6b625dbf813bf8c30c22213cb7 (patch)
tree8624d0c52b80b6de244bbca6f4ab35eb36d7cb62
parent0e432703aac3b187dd88d81ac23282f7b1c71002 (diff)
fs/9p: Add support for marking inode attribute invalid
With cached mode some of the file system operation result in updating inode attributes (ctime). Add support for marking inode attribute invalid in such cases so that we fetch the updated inode attribute on dentry revalidation. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-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,