summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-04-06 09:17:24 -0400
committerDavid Howells <dhowells@redhat.com>2018-04-09 16:53:59 -0400
commitdd9fbcb8e10349fbd640aaa5942455912004f284 (patch)
treef77b3d38b5abc531f8b47aef6a27a1ab979cc657 /fs
parent0c3a5ac28115f45ee1d56717d9a9526bc6d63b05 (diff)
afs: Rearrange status mapping
Rearrange the AFSFetchStatus to inode attribute mapping code in a number of ways: (1) Use an XDR structure rather than a series of incremented pointer accesses when decoding an AFSFetchStatus object. This allows out-of-order decode. (2) Don't store the if_version value but rather just check it and abort if it's not something we can handle. (3) Store the owner and group in the status record as raw values rather than converting them to kuid/kgid. Do that when they're mapped into i_uid/i_gid. (4) Validate the type and abort code up front and abort if they're wrong. (5) Split the inode attribute setting out into its own function from the XDR decode of an AFSFetchStatus object. This allows it to be called from elsewhere too. (6) Differentiate changes to data from changes to metadata. (7) Use the split-out attribute mapping function from afs_iget(). Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/afs/afs.h6
-rw-r--r--fs/afs/fsclient.c270
-rw-r--r--fs/afs/inode.c23
-rw-r--r--fs/afs/internal.h6
-rw-r--r--fs/afs/xdr_fs.h40
5 files changed, 216 insertions, 129 deletions
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index a670bca6d3ba..b4ff1f7ae4ab 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -131,15 +131,13 @@ struct afs_file_status {
131 afs_dataversion_t data_version; /* current data version */ 131 afs_dataversion_t data_version; /* current data version */
132 time_t mtime_client; /* last time client changed data */ 132 time_t mtime_client; /* last time client changed data */
133 time_t mtime_server; /* last time server changed data */ 133 time_t mtime_server; /* last time server changed data */
134 unsigned if_version; /* interface version */
135#define AFS_FSTATUS_VERSION 1
136 unsigned abort_code; /* Abort if bulk-fetching this failed */ 134 unsigned abort_code; /* Abort if bulk-fetching this failed */
137 135
138 afs_file_type_t type; /* file type */ 136 afs_file_type_t type; /* file type */
139 unsigned nlink; /* link count */ 137 unsigned nlink; /* link count */
140 u32 author; /* author ID */ 138 u32 author; /* author ID */
141 kuid_t owner; /* owner ID */ 139 u32 owner; /* owner ID */
142 kgid_t group; /* group ID */ 140 u32 group; /* group ID */
143 afs_access_t caller_access; /* access rights for authenticated caller */ 141 afs_access_t caller_access; /* access rights for authenticated caller */
144 afs_access_t anon_access; /* access rights for unauthenticated caller */ 142 afs_access_t anon_access; /* access rights for unauthenticated caller */
145 umode_t mode; /* UNIX mode */ 143 umode_t mode; /* UNIX mode */
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 015bbbba0858..ff87fc6bb27f 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -16,6 +16,7 @@
16#include <linux/iversion.h> 16#include <linux/iversion.h>
17#include "internal.h" 17#include "internal.h"
18#include "afs_fs.h" 18#include "afs_fs.h"
19#include "xdr_fs.h"
19 20
20static const struct afs_fid afs_zero_fid; 21static const struct afs_fid afs_zero_fid;
21 22
@@ -64,120 +65,160 @@ static void xdr_dump_bad(const __be32 *bp)
64} 65}
65 66
66/* 67/*
67 * decode an AFSFetchStatus block 68 * Update the core inode struct from a returned status record.
68 */ 69 */
69static void xdr_decode_AFSFetchStatus(const __be32 **_bp, 70void afs_update_inode_from_status(struct afs_vnode *vnode,
70 struct afs_file_status *status, 71 struct afs_file_status *status,
71 struct afs_vnode *vnode, 72 const afs_dataversion_t *expected_version,
72 const afs_dataversion_t *expected_version, 73 u8 flags)
73 afs_dataversion_t *_version)
74{ 74{
75 const __be32 *bp = *_bp; 75 struct timespec t;
76 umode_t mode; 76 umode_t mode;
77
78 t.tv_sec = status->mtime_client;
79 t.tv_nsec = 0;
80 vnode->vfs_inode.i_ctime = t;
81 vnode->vfs_inode.i_mtime = t;
82 vnode->vfs_inode.i_atime = t;
83
84 if (flags & (AFS_VNODE_META_CHANGED | AFS_VNODE_NOT_YET_SET)) {
85 vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner);
86 vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group);
87 set_nlink(&vnode->vfs_inode, status->nlink);
88
89 mode = vnode->vfs_inode.i_mode;
90 mode &= ~S_IALLUGO;
91 mode |= status->mode;
92 barrier();
93 vnode->vfs_inode.i_mode = mode;
94 }
95
96 if (!(flags & AFS_VNODE_NOT_YET_SET)) {
97 if (expected_version &&
98 *expected_version != status->data_version) {
99 _debug("vnode modified %llx on {%x:%u} [exp %llx]",
100 (unsigned long long) status->data_version,
101 vnode->fid.vid, vnode->fid.vnode,
102 (unsigned long long) *expected_version);
103 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
104 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
105 }
106 }
107
108 if (flags & (AFS_VNODE_DATA_CHANGED | AFS_VNODE_NOT_YET_SET)) {
109 inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
110 i_size_write(&vnode->vfs_inode, status->size);
111 }
112}
113
114/*
115 * decode an AFSFetchStatus block
116 */
117static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
118 struct afs_file_status *status,
119 struct afs_vnode *vnode,
120 const afs_dataversion_t *expected_version,
121 afs_dataversion_t *_version)
122{
123 const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
77 u64 data_version, size; 124 u64 data_version, size;
78 bool changed = false; 125 u32 type, abort_code;
79 kuid_t owner; 126 u8 flags = 0;
80 kgid_t group; 127 int ret;
81 128
82 if (vnode) 129 if (vnode)
83 write_seqlock(&vnode->cb_lock); 130 write_seqlock(&vnode->cb_lock);
84 131
85#define EXTRACT(DST) \ 132 if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
86 do { \ 133 pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
87 u32 x = ntohl(*bp++); \ 134 goto bad;
88 if (DST != x) \ 135 }
89 changed |= true; \
90 DST = x; \
91 } while (0)
92
93 status->if_version = ntohl(*bp++);
94 EXTRACT(status->type);
95 EXTRACT(status->nlink);
96 size = ntohl(*bp++);
97 data_version = ntohl(*bp++);
98 EXTRACT(status->author);
99 owner = make_kuid(&init_user_ns, ntohl(*bp++));
100 changed |= !uid_eq(owner, status->owner);
101 status->owner = owner;
102 EXTRACT(status->caller_access); /* call ticket dependent */
103 EXTRACT(status->anon_access);
104 EXTRACT(status->mode);
105 bp++; /* parent.vnode */
106 bp++; /* parent.unique */
107 bp++; /* seg size */
108 status->mtime_client = ntohl(*bp++);
109 status->mtime_server = ntohl(*bp++);
110 group = make_kgid(&init_user_ns, ntohl(*bp++));
111 changed |= !gid_eq(group, status->group);
112 status->group = group;
113 bp++; /* sync counter */
114 data_version |= (u64) ntohl(*bp++) << 32;
115 EXTRACT(status->lock_count);
116 size |= (u64) ntohl(*bp++) << 32;
117 EXTRACT(status->abort_code); /* spare 4 */
118 *_bp = bp;
119 136
120 switch (status->type) { 137 type = ntohl(xdr->type);
138 abort_code = ntohl(xdr->abort_code);
139 switch (type) {
121 case AFS_FTYPE_FILE: 140 case AFS_FTYPE_FILE:
122 case AFS_FTYPE_DIR: 141 case AFS_FTYPE_DIR:
123 case AFS_FTYPE_SYMLINK: 142 case AFS_FTYPE_SYMLINK:
143 if (type != status->type &&
144 vnode &&
145 !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
146 pr_warning("Vnode %x:%x:%x changed type %u to %u\n",
147 vnode->fid.vid,
148 vnode->fid.vnode,
149 vnode->fid.unique,
150 status->type, type);
151 goto bad;
152 }
153 status->type = type;
124 break; 154 break;
125 case AFS_FTYPE_INVALID: 155 case AFS_FTYPE_INVALID:
126 if (status->abort_code != 0) 156 if (abort_code != 0) {
157 status->abort_code = abort_code;
127 goto out; 158 goto out;
159 }
128 /* Fall through */ 160 /* Fall through */
129 default: 161 default:
130 xdr_dump_bad(bp - 2); 162 goto bad;
131 goto out;
132 } 163 }
133 164
165#define EXTRACT_M(FIELD) \
166 do { \
167 u32 x = ntohl(xdr->FIELD); \
168 if (status->FIELD != x) { \
169 flags |= AFS_VNODE_META_CHANGED; \
170 status->FIELD = x; \
171 } \
172 } while (0)
173
174 EXTRACT_M(nlink);
175 EXTRACT_M(author);
176 EXTRACT_M(owner);
177 EXTRACT_M(caller_access); /* call ticket dependent */
178 EXTRACT_M(anon_access);
179 EXTRACT_M(mode);
180 EXTRACT_M(group);
181
182 status->mtime_client = ntohl(xdr->mtime_client);
183 status->mtime_server = ntohl(xdr->mtime_server);
184 status->lock_count = ntohl(xdr->lock_count);
185
186 size = (u64)ntohl(xdr->size_lo);
187 size |= (u64)ntohl(xdr->size_hi) << 32;
134 if (size != status->size) { 188 if (size != status->size) {
135 status->size = size; 189 status->size = size;
136 changed |= true; 190 flags |= AFS_VNODE_DATA_CHANGED;
191 }
192
193 data_version = (u64)ntohl(xdr->data_version_lo);
194 data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
195 if (data_version != status->data_version) {
196 status->data_version = data_version;
197 flags |= AFS_VNODE_DATA_CHANGED;
137 } 198 }
138 status->mode &= S_IALLUGO;
139 if (_version) 199 if (_version)
140 *_version = data_version; 200 *_version = data_version;
141 201
142 _debug("vnode time %lx, %lx", 202 *_bp = (const void *)*_bp + sizeof(*xdr);
143 status->mtime_client, status->mtime_server);
144 203
145 if (vnode) { 204 if (vnode) {
146 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { 205 if (test_bit(AFS_VNODE_UNSET, &vnode->flags))
147 _debug("vnode changed"); 206 flags |= AFS_VNODE_NOT_YET_SET;
148 i_size_write(&vnode->vfs_inode, size); 207 afs_update_inode_from_status(vnode, status, expected_version,
149 vnode->vfs_inode.i_uid = status->owner; 208 flags);
150 vnode->vfs_inode.i_gid = status->group;
151 vnode->vfs_inode.i_generation = vnode->fid.unique;
152 set_nlink(&vnode->vfs_inode, status->nlink);
153
154 mode = vnode->vfs_inode.i_mode;
155 mode &= ~S_IALLUGO;
156 mode |= status->mode;
157 barrier();
158 vnode->vfs_inode.i_mode = mode;
159 }
160
161 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
162 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
163 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
164 inode_set_iversion_raw(&vnode->vfs_inode, data_version);
165 } 209 }
166 210
167 status->data_version = data_version; 211 ret = 0;
168 if (expected_version && *expected_version != data_version) {
169 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
170 _debug("vnode modified %llx on {%x:%u}",
171 (unsigned long long) data_version,
172 vnode->fid.vid, vnode->fid.vnode);
173 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
174 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
175 }
176 }
177 212
178out: 213out:
179 if (vnode) 214 if (vnode)
180 write_sequnlock(&vnode->cb_lock); 215 write_sequnlock(&vnode->cb_lock);
216 return ret;
217
218bad:
219 xdr_dump_bad(*_bp);
220 ret = -EBADMSG;
221 goto out;
181} 222}
182 223
183/* 224/*
@@ -319,8 +360,9 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
319 360
320 /* unmarshall the reply once we've received all of it */ 361 /* unmarshall the reply once we've received all of it */
321 bp = call->buffer; 362 bp = call->buffer;
322 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, 363 if (xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
323 &call->expected_version, NULL); 364 &call->expected_version, NULL) < 0)
365 return -EBADMSG;
324 xdr_decode_AFSCallBack(call, vnode, &bp); 366 xdr_decode_AFSCallBack(call, vnode, &bp);
325 if (call->reply[1]) 367 if (call->reply[1])
326 xdr_decode_AFSVolSync(&bp, call->reply[1]); 368 xdr_decode_AFSVolSync(&bp, call->reply[1]);
@@ -499,9 +541,10 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
499 return ret; 541 return ret;
500 542
501 bp = call->buffer; 543 bp = call->buffer;
502 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, 544 if (xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
503 &vnode->status.data_version, 545 &vnode->status.data_version,
504 &req->new_version); 546 &req->new_version) < 0)
547 return -EBADMSG;
505 xdr_decode_AFSCallBack(call, vnode, &bp); 548 xdr_decode_AFSCallBack(call, vnode, &bp);
506 if (call->reply[1]) 549 if (call->reply[1])
507 xdr_decode_AFSVolSync(&bp, call->reply[1]); 550 xdr_decode_AFSVolSync(&bp, call->reply[1]);
@@ -652,9 +695,10 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call)
652 /* unmarshall the reply once we've received all of it */ 695 /* unmarshall the reply once we've received all of it */
653 bp = call->buffer; 696 bp = call->buffer;
654 xdr_decode_AFSFid(&bp, call->reply[1]); 697 xdr_decode_AFSFid(&bp, call->reply[1]);
655 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL, NULL); 698 if (xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL, NULL) < 0 ||
656 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, 699 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
657 &call->expected_version, NULL); 700 &call->expected_version, NULL) < 0)
701 return -EBADMSG;
658 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]); 702 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
659 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ 703 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
660 704
@@ -756,8 +800,9 @@ static int afs_deliver_fs_remove(struct afs_call *call)
756 800
757 /* unmarshall the reply once we've received all of it */ 801 /* unmarshall the reply once we've received all of it */
758 bp = call->buffer; 802 bp = call->buffer;
759 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, 803 if (xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
760 &call->expected_version, NULL); 804 &call->expected_version, NULL) < 0)
805 return -EBADMSG;
761 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ 806 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
762 807
763 _leave(" = 0 [done]"); 808 _leave(" = 0 [done]");
@@ -844,9 +889,10 @@ static int afs_deliver_fs_link(struct afs_call *call)
844 889
845 /* unmarshall the reply once we've received all of it */ 890 /* unmarshall the reply once we've received all of it */
846 bp = call->buffer; 891 bp = call->buffer;
847 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL, NULL); 892 if (xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL, NULL) < 0 ||
848 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, 893 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode,
849 &call->expected_version, NULL); 894 &call->expected_version, NULL) < 0)
895 return -EBADMSG;
850 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ 896 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
851 897
852 _leave(" = 0 [done]"); 898 _leave(" = 0 [done]");
@@ -930,9 +976,10 @@ static int afs_deliver_fs_symlink(struct afs_call *call)
930 /* unmarshall the reply once we've received all of it */ 976 /* unmarshall the reply once we've received all of it */
931 bp = call->buffer; 977 bp = call->buffer;
932 xdr_decode_AFSFid(&bp, call->reply[1]); 978 xdr_decode_AFSFid(&bp, call->reply[1]);
933 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL, NULL); 979 if (xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL, NULL) ||
934 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, 980 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
935 &call->expected_version, NULL); 981 &call->expected_version, NULL) < 0)
982 return -EBADMSG;
936 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ 983 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
937 984
938 _leave(" = 0 [done]"); 985 _leave(" = 0 [done]");
@@ -1034,11 +1081,13 @@ static int afs_deliver_fs_rename(struct afs_call *call)
1034 1081
1035 /* unmarshall the reply once we've received all of it */ 1082 /* unmarshall the reply once we've received all of it */
1036 bp = call->buffer; 1083 bp = call->buffer;
1037 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, 1084 if (xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode,
1038 &call->expected_version, NULL); 1085 &call->expected_version, NULL) < 0)
1039 if (new_dvnode != orig_dvnode) 1086 return -EBADMSG;
1040 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode, 1087 if (new_dvnode != orig_dvnode &&
1041 &call->expected_version_2, NULL); 1088 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
1089 &call->expected_version_2, NULL) < 0)
1090 return -EBADMSG;
1042 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ 1091 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
1043 1092
1044 _leave(" = 0 [done]"); 1093 _leave(" = 0 [done]");
@@ -1139,8 +1188,9 @@ static int afs_deliver_fs_store_data(struct afs_call *call)
1139 1188
1140 /* unmarshall the reply once we've received all of it */ 1189 /* unmarshall the reply once we've received all of it */
1141 bp = call->buffer; 1190 bp = call->buffer;
1142 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, 1191 if (xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1143 &call->expected_version, NULL); 1192 &call->expected_version, NULL) < 0)
1193 return -EBADMSG;
1144 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ 1194 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
1145 1195
1146 afs_pages_written_back(vnode, call); 1196 afs_pages_written_back(vnode, call);
@@ -1314,8 +1364,9 @@ static int afs_deliver_fs_store_status(struct afs_call *call)
1314 1364
1315 /* unmarshall the reply once we've received all of it */ 1365 /* unmarshall the reply once we've received all of it */
1316 bp = call->buffer; 1366 bp = call->buffer;
1317 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, 1367 if (xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1318 &call->expected_version, NULL); 1368 &call->expected_version, NULL) < 0)
1369 return -EBADMSG;
1319 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ 1370 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
1320 1371
1321 _leave(" = 0 [done]"); 1372 _leave(" = 0 [done]");
@@ -2127,9 +2178,10 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2127 2178
2128 bp = call->buffer; 2179 bp = call->buffer;
2129 statuses = call->reply[1]; 2180 statuses = call->reply[1];
2130 xdr_decode_AFSFetchStatus(&bp, &statuses[call->count], 2181 if (xdr_decode_AFSFetchStatus(&bp, &statuses[call->count],
2131 call->count == 0 ? vnode : NULL, 2182 call->count == 0 ? vnode : NULL,
2132 NULL, NULL); 2183 NULL, NULL) < 0)
2184 return -EBADMSG;
2133 2185
2134 call->count++; 2186 call->count++;
2135 if (call->count < call->count2) 2187 if (call->count < call->count2)
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 488abd78dc26..2e32d475ec11 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -30,12 +30,11 @@ static const struct inode_operations afs_symlink_inode_operations = {
30}; 30};
31 31
32/* 32/*
33 * map the AFS file status to the inode member variables 33 * Initialise an inode from the vnode status.
34 */ 34 */
35static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key) 35static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key)
36{ 36{
37 struct inode *inode = AFS_VNODE_TO_I(vnode); 37 struct inode *inode = AFS_VNODE_TO_I(vnode);
38 bool changed;
39 38
40 _debug("FS: ft=%d lk=%d sz=%llu ver=%Lu mod=%hu", 39 _debug("FS: ft=%d lk=%d sz=%llu ver=%Lu mod=%hu",
41 vnode->status.type, 40 vnode->status.type,
@@ -46,6 +45,9 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
46 45
47 read_seqlock_excl(&vnode->cb_lock); 46 read_seqlock_excl(&vnode->cb_lock);
48 47
48 afs_update_inode_from_status(vnode, &vnode->status, NULL,
49 AFS_VNODE_NOT_YET_SET);
50
49 switch (vnode->status.type) { 51 switch (vnode->status.type) {
50 case AFS_FTYPE_FILE: 52 case AFS_FTYPE_FILE:
51 inode->i_mode = S_IFREG | vnode->status.mode; 53 inode->i_mode = S_IFREG | vnode->status.mode;
@@ -79,24 +81,13 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
79 return -EBADMSG; 81 return -EBADMSG;
80 } 82 }
81 83
82 changed = (vnode->status.size != inode->i_size);
83
84 set_nlink(inode, vnode->status.nlink);
85 inode->i_uid = vnode->status.owner;
86 inode->i_gid = vnode->status.group;
87 inode->i_size = vnode->status.size;
88 inode->i_ctime.tv_sec = vnode->status.mtime_client;
89 inode->i_ctime.tv_nsec = 0;
90 inode->i_atime = inode->i_mtime = inode->i_ctime;
91 inode->i_blocks = 0; 84 inode->i_blocks = 0;
92 inode->i_generation = vnode->fid.unique;
93 inode_set_iversion_raw(inode, vnode->status.data_version);
94 inode->i_mapping->a_ops = &afs_fs_aops; 85 inode->i_mapping->a_ops = &afs_fs_aops;
95 86
96 read_sequnlock_excl(&vnode->cb_lock); 87 read_sequnlock_excl(&vnode->cb_lock);
97 88
98#ifdef CONFIG_AFS_FSCACHE 89#ifdef CONFIG_AFS_FSCACHE
99 if (changed) 90 if (vnode->status.size > 0)
100 fscache_attr_changed(vnode->cache); 91 fscache_attr_changed(vnode->cache);
101#endif 92#endif
102 return 0; 93 return 0;
@@ -331,7 +322,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
331 vnode->cb_expires_at += ktime_get_real_seconds(); 322 vnode->cb_expires_at += ktime_get_real_seconds();
332 } 323 }
333 324
334 ret = afs_inode_map_status(vnode, key); 325 ret = afs_inode_init_from_status(vnode, key);
335 if (ret < 0) 326 if (ret < 0)
336 goto bad_inode; 327 goto bad_inode;
337 328
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 6b72807c40af..ac3076c2a8e8 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -704,6 +704,12 @@ extern int afs_flock(struct file *, int, struct file_lock *);
704/* 704/*
705 * fsclient.c 705 * fsclient.c
706 */ 706 */
707#define AFS_VNODE_NOT_YET_SET 0x01
708#define AFS_VNODE_META_CHANGED 0x02
709#define AFS_VNODE_DATA_CHANGED 0x04
710extern void afs_update_inode_from_status(struct afs_vnode *, struct afs_file_status *,
711 const afs_dataversion_t *, u8);
712
707extern int afs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool); 713extern int afs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool);
708extern int afs_fs_give_up_callbacks(struct afs_net *, struct afs_server *); 714extern int afs_fs_give_up_callbacks(struct afs_net *, struct afs_server *);
709extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *); 715extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *);
diff --git a/fs/afs/xdr_fs.h b/fs/afs/xdr_fs.h
new file mode 100644
index 000000000000..24e23e40c979
--- /dev/null
+++ b/fs/afs/xdr_fs.h
@@ -0,0 +1,40 @@
1/* AFS fileserver XDR types
2 *
3 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#ifndef XDR_FS_H
13#define XDR_FS_H
14
15struct afs_xdr_AFSFetchStatus {
16 __be32 if_version;
17#define AFS_FSTATUS_VERSION 1
18 __be32 type;
19 __be32 nlink;
20 __be32 size_lo;
21 __be32 data_version_lo;
22 __be32 author;
23 __be32 owner;
24 __be32 caller_access;
25 __be32 anon_access;
26 __be32 mode;
27 __be32 parent_vnode;
28 __be32 parent_unique;
29 __be32 seg_size;
30 __be32 mtime_client;
31 __be32 mtime_server;
32 __be32 group;
33 __be32 sync_counter;
34 __be32 data_version_hi;
35 __be32 lock_count;
36 __be32 size_hi;
37 __be32 abort_code;
38} __packed;
39
40#endif /* XDR_FS_H */