aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/fsclient.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2007-05-09 05:33:46 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:50 -0400
commit31143d5d515ece617ffccb7df5ff75e4d1dfa120 (patch)
treedb28c26930f6a26db3e85da90f6668061425463a /fs/afs/fsclient.c
parent416351f28d2b31d15ff73e9aff699b2163704c95 (diff)
AFS: implement basic file write support
Implement support for writing to regular AFS files, including: (1) write (2) truncate (3) fsync, fdatasync (4) chmod, chown, chgrp, utime. AFS writeback attempts to batch writes into as chunks as large as it can manage up to the point that it writes back 65535 pages in one chunk or it meets a locked page. Furthermore, if a page has been written to using a particular key, then should another write to that page use some other key, the first write will be flushed before the second is allowed to take place. If the first write fails due to a security error, then the page will be scrapped and reread before the second write takes place. If a page is dirty and the callback on it is broken by the server, then the dirty data is not discarded (same behaviour as NFS). Shared-writable mappings are not supported by this patch. [akpm@linux-foundation.org: fix a bunch of warnings] Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r--fs/afs/fsclient.c332
1 files changed, 319 insertions, 13 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 1e65fee36413..025b1903d9e1 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -33,8 +33,10 @@ static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
33 */ 33 */
34static void xdr_decode_AFSFetchStatus(const __be32 **_bp, 34static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
35 struct afs_file_status *status, 35 struct afs_file_status *status,
36 struct afs_vnode *vnode) 36 struct afs_vnode *vnode,
37 afs_dataversion_t *store_version)
37{ 38{
39 afs_dataversion_t expected_version;
38 const __be32 *bp = *_bp; 40 const __be32 *bp = *_bp;
39 umode_t mode; 41 umode_t mode;
40 u64 data_version, size; 42 u64 data_version, size;
@@ -101,7 +103,11 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
101 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; 103 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
102 } 104 }
103 105
104 if (status->data_version != data_version) { 106 expected_version = status->data_version;
107 if (store_version)
108 expected_version = *store_version;
109
110 if (expected_version != data_version) {
105 status->data_version = data_version; 111 status->data_version = data_version;
106 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { 112 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
107 _debug("vnode modified %llx on {%x:%u}", 113 _debug("vnode modified %llx on {%x:%u}",
@@ -110,6 +116,8 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
110 set_bit(AFS_VNODE_MODIFIED, &vnode->flags); 116 set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
111 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags); 117 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
112 } 118 }
119 } else if (store_version) {
120 status->data_version = data_version;
113 } 121 }
114} 122}
115 123
@@ -156,6 +164,44 @@ static void xdr_decode_AFSVolSync(const __be32 **_bp,
156} 164}
157 165
158/* 166/*
167 * encode the requested attributes into an AFSStoreStatus block
168 */
169static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
170{
171 __be32 *bp = *_bp;
172 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
173
174 mask = 0;
175 if (attr->ia_valid & ATTR_MTIME) {
176 mask |= AFS_SET_MTIME;
177 mtime = attr->ia_mtime.tv_sec;
178 }
179
180 if (attr->ia_valid & ATTR_UID) {
181 mask |= AFS_SET_OWNER;
182 owner = attr->ia_uid;
183 }
184
185 if (attr->ia_valid & ATTR_GID) {
186 mask |= AFS_SET_GROUP;
187 group = attr->ia_gid;
188 }
189
190 if (attr->ia_valid & ATTR_MODE) {
191 mask |= AFS_SET_MODE;
192 mode = attr->ia_mode & S_IALLUGO;
193 }
194
195 *bp++ = htonl(mask);
196 *bp++ = htonl(mtime);
197 *bp++ = htonl(owner);
198 *bp++ = htonl(group);
199 *bp++ = htonl(mode);
200 *bp++ = 0; /* segment size */
201 *_bp = bp;
202}
203
204/*
159 * deliver reply data to an FS.FetchStatus 205 * deliver reply data to an FS.FetchStatus
160 */ 206 */
161static int afs_deliver_fs_fetch_status(struct afs_call *call, 207static int afs_deliver_fs_fetch_status(struct afs_call *call,
@@ -175,7 +221,7 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call,
175 221
176 /* unmarshall the reply once we've received all of it */ 222 /* unmarshall the reply once we've received all of it */
177 bp = call->buffer; 223 bp = call->buffer;
178 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 224 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
179 xdr_decode_AFSCallBack(&bp, vnode); 225 xdr_decode_AFSCallBack(&bp, vnode);
180 if (call->reply2) 226 if (call->reply2)
181 xdr_decode_AFSVolSync(&bp, call->reply2); 227 xdr_decode_AFSVolSync(&bp, call->reply2);
@@ -295,7 +341,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
295 } 341 }
296 342
297 bp = call->buffer; 343 bp = call->buffer;
298 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 344 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
299 xdr_decode_AFSCallBack(&bp, vnode); 345 xdr_decode_AFSCallBack(&bp, vnode);
300 if (call->reply2) 346 if (call->reply2)
301 xdr_decode_AFSVolSync(&bp, call->reply2); 347 xdr_decode_AFSVolSync(&bp, call->reply2);
@@ -479,8 +525,8 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call,
479 /* unmarshall the reply once we've received all of it */ 525 /* unmarshall the reply once we've received all of it */
480 bp = call->buffer; 526 bp = call->buffer;
481 xdr_decode_AFSFid(&bp, call->reply2); 527 xdr_decode_AFSFid(&bp, call->reply2);
482 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL); 528 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
483 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 529 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
484 xdr_decode_AFSCallBack_raw(&bp, call->reply4); 530 xdr_decode_AFSCallBack_raw(&bp, call->reply4);
485 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 531 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
486 532
@@ -577,7 +623,7 @@ static int afs_deliver_fs_remove(struct afs_call *call,
577 623
578 /* unmarshall the reply once we've received all of it */ 624 /* unmarshall the reply once we've received all of it */
579 bp = call->buffer; 625 bp = call->buffer;
580 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 626 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
581 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 627 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
582 628
583 _leave(" = 0 [done]"); 629 _leave(" = 0 [done]");
@@ -660,8 +706,8 @@ static int afs_deliver_fs_link(struct afs_call *call,
660 706
661 /* unmarshall the reply once we've received all of it */ 707 /* unmarshall the reply once we've received all of it */
662 bp = call->buffer; 708 bp = call->buffer;
663 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 709 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
664 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode); 710 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
665 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 711 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
666 712
667 _leave(" = 0 [done]"); 713 _leave(" = 0 [done]");
@@ -749,8 +795,8 @@ static int afs_deliver_fs_symlink(struct afs_call *call,
749 /* unmarshall the reply once we've received all of it */ 795 /* unmarshall the reply once we've received all of it */
750 bp = call->buffer; 796 bp = call->buffer;
751 xdr_decode_AFSFid(&bp, call->reply2); 797 xdr_decode_AFSFid(&bp, call->reply2);
752 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL); 798 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
753 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 799 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
754 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 800 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
755 801
756 _leave(" = 0 [done]"); 802 _leave(" = 0 [done]");
@@ -855,9 +901,10 @@ static int afs_deliver_fs_rename(struct afs_call *call,
855 901
856 /* unmarshall the reply once we've received all of it */ 902 /* unmarshall the reply once we've received all of it */
857 bp = call->buffer; 903 bp = call->buffer;
858 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode); 904 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
859 if (new_dvnode != orig_dvnode) 905 if (new_dvnode != orig_dvnode)
860 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode); 906 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
907 NULL);
861 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 908 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
862 909
863 _leave(" = 0 [done]"); 910 _leave(" = 0 [done]");
@@ -939,3 +986,262 @@ int afs_fs_rename(struct afs_server *server,
939 986
940 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 987 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
941} 988}
989
990/*
991 * deliver reply data to an FS.StoreData
992 */
993static int afs_deliver_fs_store_data(struct afs_call *call,
994 struct sk_buff *skb, bool last)
995{
996 struct afs_vnode *vnode = call->reply;
997 const __be32 *bp;
998
999 _enter(",,%u", last);
1000
1001 afs_transfer_reply(call, skb);
1002 if (!last) {
1003 _leave(" = 0 [more]");
1004 return 0;
1005 }
1006
1007 if (call->reply_size != call->reply_max) {
1008 _leave(" = -EBADMSG [%u != %u]",
1009 call->reply_size, call->reply_max);
1010 return -EBADMSG;
1011 }
1012
1013 /* unmarshall the reply once we've received all of it */
1014 bp = call->buffer;
1015 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1016 &call->store_version);
1017 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1018
1019 afs_pages_written_back(vnode, call);
1020
1021 _leave(" = 0 [done]");
1022 return 0;
1023}
1024
1025/*
1026 * FS.StoreData operation type
1027 */
1028static const struct afs_call_type afs_RXFSStoreData = {
1029 .name = "FS.StoreData",
1030 .deliver = afs_deliver_fs_store_data,
1031 .abort_to_error = afs_abort_to_error,
1032 .destructor = afs_flat_call_destructor,
1033};
1034
1035/*
1036 * store a set of pages
1037 */
1038int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
1039 pgoff_t first, pgoff_t last,
1040 unsigned offset, unsigned to,
1041 const struct afs_wait_mode *wait_mode)
1042{
1043 struct afs_vnode *vnode = wb->vnode;
1044 struct afs_call *call;
1045 loff_t size, pos, i_size;
1046 __be32 *bp;
1047
1048 _enter(",%x,{%x:%u},,",
1049 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1050
1051 size = to - offset;
1052 if (first != last)
1053 size += (loff_t)(last - first) << PAGE_SHIFT;
1054 pos = (loff_t)first << PAGE_SHIFT;
1055 pos += offset;
1056
1057 i_size = i_size_read(&vnode->vfs_inode);
1058 if (pos + size > i_size)
1059 i_size = size + pos;
1060
1061 _debug("size %llx, at %llx, i_size %llx",
1062 (unsigned long long) size, (unsigned long long) pos,
1063 (unsigned long long) i_size);
1064
1065 BUG_ON(i_size > 0xffffffff); // TODO: use 64-bit store
1066
1067 call = afs_alloc_flat_call(&afs_RXFSStoreData,
1068 (4 + 6 + 3) * 4,
1069 (21 + 6) * 4);
1070 if (!call)
1071 return -ENOMEM;
1072
1073 call->wb = wb;
1074 call->key = wb->key;
1075 call->reply = vnode;
1076 call->service_id = FS_SERVICE;
1077 call->port = htons(AFS_FS_PORT);
1078 call->mapping = vnode->vfs_inode.i_mapping;
1079 call->first = first;
1080 call->last = last;
1081 call->first_offset = offset;
1082 call->last_to = to;
1083 call->send_pages = true;
1084 call->store_version = vnode->status.data_version + 1;
1085
1086 /* marshall the parameters */
1087 bp = call->request;
1088 *bp++ = htonl(FSSTOREDATA);
1089 *bp++ = htonl(vnode->fid.vid);
1090 *bp++ = htonl(vnode->fid.vnode);
1091 *bp++ = htonl(vnode->fid.unique);
1092
1093 *bp++ = 0; /* mask */
1094 *bp++ = 0; /* mtime */
1095 *bp++ = 0; /* owner */
1096 *bp++ = 0; /* group */
1097 *bp++ = 0; /* unix mode */
1098 *bp++ = 0; /* segment size */
1099
1100 *bp++ = htonl(pos);
1101 *bp++ = htonl(size);
1102 *bp++ = htonl(i_size);
1103
1104 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1105}
1106
1107/*
1108 * deliver reply data to an FS.StoreStatus
1109 */
1110static int afs_deliver_fs_store_status(struct afs_call *call,
1111 struct sk_buff *skb, bool last)
1112{
1113 afs_dataversion_t *store_version;
1114 struct afs_vnode *vnode = call->reply;
1115 const __be32 *bp;
1116
1117 _enter(",,%u", last);
1118
1119 afs_transfer_reply(call, skb);
1120 if (!last) {
1121 _leave(" = 0 [more]");
1122 return 0;
1123 }
1124
1125 if (call->reply_size != call->reply_max) {
1126 _leave(" = -EBADMSG [%u != %u]",
1127 call->reply_size, call->reply_max);
1128 return -EBADMSG;
1129 }
1130
1131 /* unmarshall the reply once we've received all of it */
1132 store_version = NULL;
1133 if (call->operation_ID == FSSTOREDATA)
1134 store_version = &call->store_version;
1135
1136 bp = call->buffer;
1137 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
1138 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1139
1140 _leave(" = 0 [done]");
1141 return 0;
1142}
1143
1144/*
1145 * FS.StoreStatus operation type
1146 */
1147static const struct afs_call_type afs_RXFSStoreStatus = {
1148 .name = "FS.StoreStatus",
1149 .deliver = afs_deliver_fs_store_status,
1150 .abort_to_error = afs_abort_to_error,
1151 .destructor = afs_flat_call_destructor,
1152};
1153
1154static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1155 .name = "FS.StoreData",
1156 .deliver = afs_deliver_fs_store_status,
1157 .abort_to_error = afs_abort_to_error,
1158 .destructor = afs_flat_call_destructor,
1159};
1160
1161/*
1162 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1163 * so as to alter the file size also
1164 */
1165static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
1166 struct afs_vnode *vnode, struct iattr *attr,
1167 const struct afs_wait_mode *wait_mode)
1168{
1169 struct afs_call *call;
1170 __be32 *bp;
1171
1172 _enter(",%x,{%x:%u},,",
1173 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1174
1175 ASSERT(attr->ia_valid & ATTR_SIZE);
1176 ASSERTCMP(attr->ia_size, <=, 0xffffffff); // TODO: use 64-bit store
1177
1178 call = afs_alloc_flat_call(&afs_RXFSStoreData_as_Status,
1179 (4 + 6 + 3) * 4,
1180 (21 + 6) * 4);
1181 if (!call)
1182 return -ENOMEM;
1183
1184 call->key = key;
1185 call->reply = vnode;
1186 call->service_id = FS_SERVICE;
1187 call->port = htons(AFS_FS_PORT);
1188 call->store_version = vnode->status.data_version + 1;
1189 call->operation_ID = FSSTOREDATA;
1190
1191 /* marshall the parameters */
1192 bp = call->request;
1193 *bp++ = htonl(FSSTOREDATA);
1194 *bp++ = htonl(vnode->fid.vid);
1195 *bp++ = htonl(vnode->fid.vnode);
1196 *bp++ = htonl(vnode->fid.unique);
1197
1198 xdr_encode_AFS_StoreStatus(&bp, attr);
1199
1200 *bp++ = 0; /* position of start of write */
1201 *bp++ = 0; /* size of write */
1202 *bp++ = htonl(attr->ia_size); /* new file length */
1203
1204 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1205}
1206
1207/*
1208 * set the attributes on a file, using FS.StoreData if there's a change in file
1209 * size, and FS.StoreStatus otherwise
1210 */
1211int afs_fs_setattr(struct afs_server *server, struct key *key,
1212 struct afs_vnode *vnode, struct iattr *attr,
1213 const struct afs_wait_mode *wait_mode)
1214{
1215 struct afs_call *call;
1216 __be32 *bp;
1217
1218 if (attr->ia_valid & ATTR_SIZE)
1219 return afs_fs_setattr_size(server, key, vnode, attr,
1220 wait_mode);
1221
1222 _enter(",%x,{%x:%u},,",
1223 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1224
1225 call = afs_alloc_flat_call(&afs_RXFSStoreStatus,
1226 (4 + 6) * 4,
1227 (21 + 6) * 4);
1228 if (!call)
1229 return -ENOMEM;
1230
1231 call->key = key;
1232 call->reply = vnode;
1233 call->service_id = FS_SERVICE;
1234 call->port = htons(AFS_FS_PORT);
1235 call->operation_ID = FSSTORESTATUS;
1236
1237 /* marshall the parameters */
1238 bp = call->request;
1239 *bp++ = htonl(FSSTORESTATUS);
1240 *bp++ = htonl(vnode->fid.vid);
1241 *bp++ = htonl(vnode->fid.vnode);
1242 *bp++ = htonl(vnode->fid.unique);
1243
1244 xdr_encode_AFS_StoreStatus(&bp, attr);
1245
1246 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1247}