diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-01 22:58:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-01 22:58:52 -0400 |
commit | 9931a07d518e86eb58a75e508ed9626f86359303 (patch) | |
tree | 8c3be85875e35ab14a14143f2499be924f149a46 | |
parent | e468f5c06b5ebef3f6f3c187e51aa6daab667e57 (diff) | |
parent | 0e9b4a82710220c04100892fb7277b78fd33a747 (diff) |
Merge branch 'work.afs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull AFS updates from Al Viro:
"AFS series, with some iov_iter bits included"
* 'work.afs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (26 commits)
missing bits of "iov_iter: Separate type from direction and use accessor functions"
afs: Probe multiple fileservers simultaneously
afs: Fix callback handling
afs: Eliminate the address pointer from the address list cursor
afs: Allow dumping of server cursor on operation failure
afs: Implement YFS support in the fs client
afs: Expand data structure fields to support YFS
afs: Get the target vnode in afs_rmdir() and get a callback on it
afs: Calc callback expiry in op reply delivery
afs: Fix FS.FetchStatus delivery from updating wrong vnode
afs: Implement the YFS cache manager service
afs: Remove callback details from afs_callback_break struct
afs: Commit the status on a new file/dir/symlink
afs: Increase to 64-bit volume ID and 96-bit vnode ID for YFS
afs: Don't invoke the server to read data beyond EOF
afs: Add a couple of tracepoints to log I/O errors
afs: Handle EIO from delivery function
afs: Fix TTL on VL server and address lists
afs: Implement VL server rotation
afs: Improve FS server rotation error handling
...
85 files changed, 5632 insertions, 1239 deletions
diff --git a/block/bio.c b/block/bio.c index bbfeb4ee2892..c27f77befbac 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -1256,7 +1256,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
1256 | /* | 1256 | /* |
1257 | * success | 1257 | * success |
1258 | */ | 1258 | */ |
1259 | if (((iter->type & WRITE) && (!map_data || !map_data->null_mapped)) || | 1259 | if ((iov_iter_rw(iter) == WRITE && (!map_data || !map_data->null_mapped)) || |
1260 | (map_data && map_data->from_user)) { | 1260 | (map_data && map_data->from_user)) { |
1261 | ret = bio_copy_from_iter(bio, iter); | 1261 | ret = bio_copy_from_iter(bio, iter); |
1262 | if (ret) | 1262 | if (ret) |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 55fd104f1ed4..fa8204214ac0 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -1856,7 +1856,7 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock, | |||
1856 | 1856 | ||
1857 | /* THINK if (signal_pending) return ... ? */ | 1857 | /* THINK if (signal_pending) return ... ? */ |
1858 | 1858 | ||
1859 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1, size); | 1859 | iov_iter_kvec(&msg.msg_iter, WRITE, &iov, 1, size); |
1860 | 1860 | ||
1861 | if (sock == connection->data.socket) { | 1861 | if (sock == connection->data.socket) { |
1862 | rcu_read_lock(); | 1862 | rcu_read_lock(); |
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index fc67fd853375..61c392752fe4 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -516,7 +516,7 @@ static int drbd_recv_short(struct socket *sock, void *buf, size_t size, int flag | |||
516 | struct msghdr msg = { | 516 | struct msghdr msg = { |
517 | .msg_flags = (flags ? flags : MSG_WAITALL | MSG_NOSIGNAL) | 517 | .msg_flags = (flags ? flags : MSG_WAITALL | MSG_NOSIGNAL) |
518 | }; | 518 | }; |
519 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, size); | 519 | iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, size); |
520 | return sock_recvmsg(sock, &msg, msg.msg_flags); | 520 | return sock_recvmsg(sock, &msg, msg.msg_flags); |
521 | } | 521 | } |
522 | 522 | ||
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index abad6d15f956..e6273ae85246 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -269,7 +269,7 @@ static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos) | |||
269 | struct iov_iter i; | 269 | struct iov_iter i; |
270 | ssize_t bw; | 270 | ssize_t bw; |
271 | 271 | ||
272 | iov_iter_bvec(&i, ITER_BVEC | WRITE, bvec, 1, bvec->bv_len); | 272 | iov_iter_bvec(&i, WRITE, bvec, 1, bvec->bv_len); |
273 | 273 | ||
274 | file_start_write(file); | 274 | file_start_write(file); |
275 | bw = vfs_iter_write(file, &i, ppos, 0); | 275 | bw = vfs_iter_write(file, &i, ppos, 0); |
@@ -347,7 +347,7 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq, | |||
347 | ssize_t len; | 347 | ssize_t len; |
348 | 348 | ||
349 | rq_for_each_segment(bvec, rq, iter) { | 349 | rq_for_each_segment(bvec, rq, iter) { |
350 | iov_iter_bvec(&i, ITER_BVEC, &bvec, 1, bvec.bv_len); | 350 | iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len); |
351 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); | 351 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); |
352 | if (len < 0) | 352 | if (len < 0) |
353 | return len; | 353 | return len; |
@@ -388,7 +388,7 @@ static int lo_read_transfer(struct loop_device *lo, struct request *rq, | |||
388 | b.bv_offset = 0; | 388 | b.bv_offset = 0; |
389 | b.bv_len = bvec.bv_len; | 389 | b.bv_len = bvec.bv_len; |
390 | 390 | ||
391 | iov_iter_bvec(&i, ITER_BVEC, &b, 1, b.bv_len); | 391 | iov_iter_bvec(&i, READ, &b, 1, b.bv_len); |
392 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); | 392 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); |
393 | if (len < 0) { | 393 | if (len < 0) { |
394 | ret = len; | 394 | ret = len; |
@@ -555,8 +555,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, | |||
555 | } | 555 | } |
556 | atomic_set(&cmd->ref, 2); | 556 | atomic_set(&cmd->ref, 2); |
557 | 557 | ||
558 | iov_iter_bvec(&iter, ITER_BVEC | rw, bvec, | 558 | iov_iter_bvec(&iter, rw, bvec, segments, blk_rq_bytes(rq)); |
559 | segments, blk_rq_bytes(rq)); | ||
560 | iter.iov_offset = offset; | 559 | iter.iov_offset = offset; |
561 | 560 | ||
562 | cmd->iocb.ki_pos = pos; | 561 | cmd->iocb.ki_pos = pos; |
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 14a51254c3db..4d4d6129ff66 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -473,7 +473,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) | |||
473 | u32 nbd_cmd_flags = 0; | 473 | u32 nbd_cmd_flags = 0; |
474 | int sent = nsock->sent, skip = 0; | 474 | int sent = nsock->sent, skip = 0; |
475 | 475 | ||
476 | iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request)); | 476 | iov_iter_kvec(&from, WRITE, &iov, 1, sizeof(request)); |
477 | 477 | ||
478 | switch (req_op(req)) { | 478 | switch (req_op(req)) { |
479 | case REQ_OP_DISCARD: | 479 | case REQ_OP_DISCARD: |
@@ -564,8 +564,7 @@ send_pages: | |||
564 | 564 | ||
565 | dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n", | 565 | dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n", |
566 | req, bvec.bv_len); | 566 | req, bvec.bv_len); |
567 | iov_iter_bvec(&from, ITER_BVEC | WRITE, | 567 | iov_iter_bvec(&from, WRITE, &bvec, 1, bvec.bv_len); |
568 | &bvec, 1, bvec.bv_len); | ||
569 | if (skip) { | 568 | if (skip) { |
570 | if (skip >= iov_iter_count(&from)) { | 569 | if (skip >= iov_iter_count(&from)) { |
571 | skip -= iov_iter_count(&from); | 570 | skip -= iov_iter_count(&from); |
@@ -624,7 +623,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) | |||
624 | int ret = 0; | 623 | int ret = 0; |
625 | 624 | ||
626 | reply.magic = 0; | 625 | reply.magic = 0; |
627 | iov_iter_kvec(&to, READ | ITER_KVEC, &iov, 1, sizeof(reply)); | 626 | iov_iter_kvec(&to, READ, &iov, 1, sizeof(reply)); |
628 | result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL); | 627 | result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL); |
629 | if (result <= 0) { | 628 | if (result <= 0) { |
630 | if (!nbd_disconnected(config)) | 629 | if (!nbd_disconnected(config)) |
@@ -678,8 +677,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) | |||
678 | struct bio_vec bvec; | 677 | struct bio_vec bvec; |
679 | 678 | ||
680 | rq_for_each_segment(bvec, req, iter) { | 679 | rq_for_each_segment(bvec, req, iter) { |
681 | iov_iter_bvec(&to, ITER_BVEC | READ, | 680 | iov_iter_bvec(&to, READ, &bvec, 1, bvec.bv_len); |
682 | &bvec, 1, bvec.bv_len); | ||
683 | result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL); | 681 | result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL); |
684 | if (result <= 0) { | 682 | if (result <= 0) { |
685 | dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n", | 683 | dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n", |
@@ -1073,7 +1071,7 @@ static void send_disconnects(struct nbd_device *nbd) | |||
1073 | for (i = 0; i < config->num_connections; i++) { | 1071 | for (i = 0; i < config->num_connections; i++) { |
1074 | struct nbd_sock *nsock = config->socks[i]; | 1072 | struct nbd_sock *nsock = config->socks[i]; |
1075 | 1073 | ||
1076 | iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request)); | 1074 | iov_iter_kvec(&from, WRITE, &iov, 1, sizeof(request)); |
1077 | mutex_lock(&nsock->tx_lock); | 1075 | mutex_lock(&nsock->tx_lock); |
1078 | ret = sock_xmit(nbd, i, 1, &from, 0, NULL); | 1076 | ret = sock_xmit(nbd, i, 1, &from, 0, NULL); |
1079 | if (ret <= 0) | 1077 | if (ret <= 0) |
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c index ae861342626e..d92f5b87c251 100644 --- a/drivers/fsi/fsi-sbefifo.c +++ b/drivers/fsi/fsi-sbefifo.c | |||
@@ -638,7 +638,7 @@ static void sbefifo_collect_async_ffdc(struct sbefifo *sbefifo) | |||
638 | } | 638 | } |
639 | ffdc_iov.iov_base = ffdc; | 639 | ffdc_iov.iov_base = ffdc; |
640 | ffdc_iov.iov_len = SBEFIFO_MAX_FFDC_SIZE; | 640 | ffdc_iov.iov_len = SBEFIFO_MAX_FFDC_SIZE; |
641 | iov_iter_kvec(&ffdc_iter, WRITE | ITER_KVEC, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE); | 641 | iov_iter_kvec(&ffdc_iter, WRITE, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE); |
642 | cmd[0] = cpu_to_be32(2); | 642 | cmd[0] = cpu_to_be32(2); |
643 | cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_SBE_FFDC); | 643 | cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_SBE_FFDC); |
644 | rc = sbefifo_do_command(sbefifo, cmd, 2, &ffdc_iter); | 644 | rc = sbefifo_do_command(sbefifo, cmd, 2, &ffdc_iter); |
@@ -735,7 +735,7 @@ int sbefifo_submit(struct device *dev, const __be32 *command, size_t cmd_len, | |||
735 | rbytes = (*resp_len) * sizeof(__be32); | 735 | rbytes = (*resp_len) * sizeof(__be32); |
736 | resp_iov.iov_base = response; | 736 | resp_iov.iov_base = response; |
737 | resp_iov.iov_len = rbytes; | 737 | resp_iov.iov_len = rbytes; |
738 | iov_iter_kvec(&resp_iter, WRITE | ITER_KVEC, &resp_iov, 1, rbytes); | 738 | iov_iter_kvec(&resp_iter, WRITE, &resp_iov, 1, rbytes); |
739 | 739 | ||
740 | /* Perform the command */ | 740 | /* Perform the command */ |
741 | mutex_lock(&sbefifo->lock); | 741 | mutex_lock(&sbefifo->lock); |
diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index a407892905af..c0d9f332baed 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h | |||
@@ -40,8 +40,6 @@ | |||
40 | #define LITTLEENDIAN_CPU | 40 | #define LITTLEENDIAN_CPU |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | #undef READ | ||
44 | #undef WRITE | ||
45 | #undef FRAME_SIZE | 43 | #undef FRAME_SIZE |
46 | 44 | ||
47 | #define dm_output_to_console(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) | 45 | #define dm_output_to_console(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) |
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index b05022f94f18..072bb5e36c18 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c | |||
@@ -718,8 +718,7 @@ l1oip_socket_thread(void *data) | |||
718 | printk(KERN_DEBUG "%s: socket created and open\n", | 718 | printk(KERN_DEBUG "%s: socket created and open\n", |
719 | __func__); | 719 | __func__); |
720 | while (!signal_pending(current)) { | 720 | while (!signal_pending(current)) { |
721 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, | 721 | iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, recvbuf_size); |
722 | recvbuf_size); | ||
723 | recvlen = sock_recvmsg(socket, &msg, 0); | 722 | recvlen = sock_recvmsg(socket, &msg, 0); |
724 | if (recvlen > 0) { | 723 | if (recvlen > 0) { |
725 | l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen); | 724 | l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen); |
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index bd52f29b4a4e..264f4ed8eef2 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c | |||
@@ -3030,7 +3030,7 @@ ssize_t vmci_qpair_enqueue(struct vmci_qp *qpair, | |||
3030 | if (!qpair || !buf) | 3030 | if (!qpair || !buf) |
3031 | return VMCI_ERROR_INVALID_ARGS; | 3031 | return VMCI_ERROR_INVALID_ARGS; |
3032 | 3032 | ||
3033 | iov_iter_kvec(&from, WRITE | ITER_KVEC, &v, 1, buf_size); | 3033 | iov_iter_kvec(&from, WRITE, &v, 1, buf_size); |
3034 | 3034 | ||
3035 | qp_lock(qpair); | 3035 | qp_lock(qpair); |
3036 | 3036 | ||
@@ -3074,7 +3074,7 @@ ssize_t vmci_qpair_dequeue(struct vmci_qp *qpair, | |||
3074 | if (!qpair || !buf) | 3074 | if (!qpair || !buf) |
3075 | return VMCI_ERROR_INVALID_ARGS; | 3075 | return VMCI_ERROR_INVALID_ARGS; |
3076 | 3076 | ||
3077 | iov_iter_kvec(&to, READ | ITER_KVEC, &v, 1, buf_size); | 3077 | iov_iter_kvec(&to, READ, &v, 1, buf_size); |
3078 | 3078 | ||
3079 | qp_lock(qpair); | 3079 | qp_lock(qpair); |
3080 | 3080 | ||
@@ -3119,7 +3119,7 @@ ssize_t vmci_qpair_peek(struct vmci_qp *qpair, | |||
3119 | if (!qpair || !buf) | 3119 | if (!qpair || !buf) |
3120 | return VMCI_ERROR_INVALID_ARGS; | 3120 | return VMCI_ERROR_INVALID_ARGS; |
3121 | 3121 | ||
3122 | iov_iter_kvec(&to, READ | ITER_KVEC, &v, 1, buf_size); | 3122 | iov_iter_kvec(&to, READ, &v, 1, buf_size); |
3123 | 3123 | ||
3124 | qp_lock(qpair); | 3124 | qp_lock(qpair); |
3125 | 3125 | ||
diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c index 39d972e2595f..01feebec29ea 100644 --- a/drivers/nvme/target/io-cmd-file.c +++ b/drivers/nvme/target/io-cmd-file.c | |||
@@ -101,7 +101,7 @@ static ssize_t nvmet_file_submit_bvec(struct nvmet_req *req, loff_t pos, | |||
101 | rw = READ; | 101 | rw = READ; |
102 | } | 102 | } |
103 | 103 | ||
104 | iov_iter_bvec(&iter, ITER_BVEC | rw, req->f.bvec, nr_segs, count); | 104 | iov_iter_bvec(&iter, rw, req->f.bvec, nr_segs, count); |
105 | 105 | ||
106 | iocb->ki_pos = pos; | 106 | iocb->ki_pos = pos; |
107 | iocb->ki_filp = req->ns->file; | 107 | iocb->ki_filp = req->ns->file; |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 1227872227dc..36b742932c72 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -1245,8 +1245,7 @@ static int iscsit_do_rx_data( | |||
1245 | return -1; | 1245 | return -1; |
1246 | 1246 | ||
1247 | memset(&msg, 0, sizeof(struct msghdr)); | 1247 | memset(&msg, 0, sizeof(struct msghdr)); |
1248 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, | 1248 | iov_iter_kvec(&msg.msg_iter, READ, count->iov, count->iov_count, data); |
1249 | count->iov, count->iov_count, data); | ||
1250 | 1249 | ||
1251 | while (msg_data_left(&msg)) { | 1250 | while (msg_data_left(&msg)) { |
1252 | rx_loop = sock_recvmsg(conn->sock, &msg, MSG_WAITALL); | 1251 | rx_loop = sock_recvmsg(conn->sock, &msg, MSG_WAITALL); |
@@ -1302,8 +1301,7 @@ int tx_data( | |||
1302 | 1301 | ||
1303 | memset(&msg, 0, sizeof(struct msghdr)); | 1302 | memset(&msg, 0, sizeof(struct msghdr)); |
1304 | 1303 | ||
1305 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, | 1304 | iov_iter_kvec(&msg.msg_iter, WRITE, iov, iov_count, data); |
1306 | iov, iov_count, data); | ||
1307 | 1305 | ||
1308 | while (msg_data_left(&msg)) { | 1306 | while (msg_data_left(&msg)) { |
1309 | int tx_loop = sock_sendmsg(conn->sock, &msg); | 1307 | int tx_loop = sock_sendmsg(conn->sock, &msg); |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 16751ae55d7b..49b110d1b972 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -303,7 +303,7 @@ fd_execute_rw_aio(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
303 | len += sg->length; | 303 | len += sg->length; |
304 | } | 304 | } |
305 | 305 | ||
306 | iov_iter_bvec(&iter, ITER_BVEC | is_write, bvec, sgl_nents, len); | 306 | iov_iter_bvec(&iter, is_write, bvec, sgl_nents, len); |
307 | 307 | ||
308 | aio_cmd->cmd = cmd; | 308 | aio_cmd->cmd = cmd; |
309 | aio_cmd->len = len; | 309 | aio_cmd->len = len; |
@@ -353,7 +353,7 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd, | |||
353 | len += sg->length; | 353 | len += sg->length; |
354 | } | 354 | } |
355 | 355 | ||
356 | iov_iter_bvec(&iter, ITER_BVEC, bvec, sgl_nents, len); | 356 | iov_iter_bvec(&iter, READ, bvec, sgl_nents, len); |
357 | if (is_write) | 357 | if (is_write) |
358 | ret = vfs_iter_write(fd, &iter, &pos, 0); | 358 | ret = vfs_iter_write(fd, &iter, &pos, 0); |
359 | else | 359 | else |
@@ -490,7 +490,7 @@ fd_execute_write_same(struct se_cmd *cmd) | |||
490 | len += se_dev->dev_attrib.block_size; | 490 | len += se_dev->dev_attrib.block_size; |
491 | } | 491 | } |
492 | 492 | ||
493 | iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len); | 493 | iov_iter_bvec(&iter, READ, bvec, nolb, len); |
494 | ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos, 0); | 494 | ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos, 0); |
495 | 495 | ||
496 | kfree(bvec); | 496 | kfree(bvec); |
diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c index 9756752c0681..45da3e01c7b0 100644 --- a/drivers/usb/usbip/usbip_common.c +++ b/drivers/usb/usbip/usbip_common.c | |||
@@ -309,7 +309,7 @@ int usbip_recv(struct socket *sock, void *buf, int size) | |||
309 | if (!sock || !buf || !size) | 309 | if (!sock || !buf || !size) |
310 | return -EINVAL; | 310 | return -EINVAL; |
311 | 311 | ||
312 | iov_iter_kvec(&msg.msg_iter, READ|ITER_KVEC, &iov, 1, size); | 312 | iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, size); |
313 | 313 | ||
314 | usbip_dbg_xmit("enter\n"); | 314 | usbip_dbg_xmit("enter\n"); |
315 | 315 | ||
diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c index b1092fbefa63..2e5d845b5091 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c | |||
@@ -137,13 +137,13 @@ static void pvcalls_conn_back_read(void *opaque) | |||
137 | if (masked_prod < masked_cons) { | 137 | if (masked_prod < masked_cons) { |
138 | vec[0].iov_base = data->in + masked_prod; | 138 | vec[0].iov_base = data->in + masked_prod; |
139 | vec[0].iov_len = wanted; | 139 | vec[0].iov_len = wanted; |
140 | iov_iter_kvec(&msg.msg_iter, ITER_KVEC|WRITE, vec, 1, wanted); | 140 | iov_iter_kvec(&msg.msg_iter, WRITE, vec, 1, wanted); |
141 | } else { | 141 | } else { |
142 | vec[0].iov_base = data->in + masked_prod; | 142 | vec[0].iov_base = data->in + masked_prod; |
143 | vec[0].iov_len = array_size - masked_prod; | 143 | vec[0].iov_len = array_size - masked_prod; |
144 | vec[1].iov_base = data->in; | 144 | vec[1].iov_base = data->in; |
145 | vec[1].iov_len = wanted - vec[0].iov_len; | 145 | vec[1].iov_len = wanted - vec[0].iov_len; |
146 | iov_iter_kvec(&msg.msg_iter, ITER_KVEC|WRITE, vec, 2, wanted); | 146 | iov_iter_kvec(&msg.msg_iter, WRITE, vec, 2, wanted); |
147 | } | 147 | } |
148 | 148 | ||
149 | atomic_set(&map->read, 0); | 149 | atomic_set(&map->read, 0); |
@@ -195,13 +195,13 @@ static void pvcalls_conn_back_write(struct sock_mapping *map) | |||
195 | if (pvcalls_mask(prod, array_size) > pvcalls_mask(cons, array_size)) { | 195 | if (pvcalls_mask(prod, array_size) > pvcalls_mask(cons, array_size)) { |
196 | vec[0].iov_base = data->out + pvcalls_mask(cons, array_size); | 196 | vec[0].iov_base = data->out + pvcalls_mask(cons, array_size); |
197 | vec[0].iov_len = size; | 197 | vec[0].iov_len = size; |
198 | iov_iter_kvec(&msg.msg_iter, ITER_KVEC|READ, vec, 1, size); | 198 | iov_iter_kvec(&msg.msg_iter, READ, vec, 1, size); |
199 | } else { | 199 | } else { |
200 | vec[0].iov_base = data->out + pvcalls_mask(cons, array_size); | 200 | vec[0].iov_base = data->out + pvcalls_mask(cons, array_size); |
201 | vec[0].iov_len = array_size - pvcalls_mask(cons, array_size); | 201 | vec[0].iov_len = array_size - pvcalls_mask(cons, array_size); |
202 | vec[1].iov_base = data->out; | 202 | vec[1].iov_base = data->out; |
203 | vec[1].iov_len = size - vec[0].iov_len; | 203 | vec[1].iov_len = size - vec[0].iov_len; |
204 | iov_iter_kvec(&msg.msg_iter, ITER_KVEC|READ, vec, 2, size); | 204 | iov_iter_kvec(&msg.msg_iter, READ, vec, 2, size); |
205 | } | 205 | } |
206 | 206 | ||
207 | atomic_set(&map->write, 0); | 207 | atomic_set(&map->write, 0); |
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index e1cbdfdb7c68..0bcbcc20f769 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c | |||
@@ -65,7 +65,7 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) | |||
65 | if (retval == 0) | 65 | if (retval == 0) |
66 | return retval; | 66 | return retval; |
67 | 67 | ||
68 | iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE); | 68 | iov_iter_bvec(&to, READ, &bvec, 1, PAGE_SIZE); |
69 | 69 | ||
70 | retval = p9_client_read(fid, page_offset(page), &to, &err); | 70 | retval = p9_client_read(fid, page_offset(page), &to, &err); |
71 | if (err) { | 71 | if (err) { |
@@ -175,7 +175,7 @@ static int v9fs_vfs_writepage_locked(struct page *page) | |||
175 | bvec.bv_page = page; | 175 | bvec.bv_page = page; |
176 | bvec.bv_offset = 0; | 176 | bvec.bv_offset = 0; |
177 | bvec.bv_len = len; | 177 | bvec.bv_len = len; |
178 | iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len); | 178 | iov_iter_bvec(&from, WRITE, &bvec, 1, len); |
179 | 179 | ||
180 | /* We should have writeback_fid always set */ | 180 | /* We should have writeback_fid always set */ |
181 | BUG_ON(!v9inode->writeback_fid); | 181 | BUG_ON(!v9inode->writeback_fid); |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index cb6c4031af55..00745147329d 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -123,7 +123,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |||
123 | if (rdir->tail == rdir->head) { | 123 | if (rdir->tail == rdir->head) { |
124 | struct iov_iter to; | 124 | struct iov_iter to; |
125 | int n; | 125 | int n; |
126 | iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); | 126 | iov_iter_kvec(&to, READ, &kvec, 1, buflen); |
127 | n = p9_client_read(file->private_data, ctx->pos, &to, | 127 | n = p9_client_read(file->private_data, ctx->pos, &to, |
128 | &err); | 128 | &err); |
129 | if (err) | 129 | if (err) |
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index 352abc39e891..ac8ff8ca4c11 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c | |||
@@ -32,7 +32,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, | |||
32 | struct iov_iter to; | 32 | struct iov_iter to; |
33 | int err; | 33 | int err; |
34 | 34 | ||
35 | iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size); | 35 | iov_iter_kvec(&to, READ, &kvec, 1, buffer_size); |
36 | 36 | ||
37 | attr_fid = p9_client_xattrwalk(fid, name, &attr_size); | 37 | attr_fid = p9_client_xattrwalk(fid, name, &attr_size); |
38 | if (IS_ERR(attr_fid)) { | 38 | if (IS_ERR(attr_fid)) { |
@@ -107,7 +107,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, | |||
107 | struct iov_iter from; | 107 | struct iov_iter from; |
108 | int retval, err; | 108 | int retval, err; |
109 | 109 | ||
110 | iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len); | 110 | iov_iter_kvec(&from, WRITE, &kvec, 1, value_len); |
111 | 111 | ||
112 | p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", | 112 | p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", |
113 | name, value_len, flags); | 113 | name, value_len, flags); |
diff --git a/fs/afs/Kconfig b/fs/afs/Kconfig index ebba3b18e5da..701aaa9b1899 100644 --- a/fs/afs/Kconfig +++ b/fs/afs/Kconfig | |||
@@ -27,3 +27,15 @@ config AFS_FSCACHE | |||
27 | help | 27 | help |
28 | Say Y here if you want AFS data to be cached locally on disk through | 28 | Say Y here if you want AFS data to be cached locally on disk through |
29 | the generic filesystem cache manager | 29 | the generic filesystem cache manager |
30 | |||
31 | config AFS_DEBUG_CURSOR | ||
32 | bool "AFS server cursor debugging" | ||
33 | depends on AFS_FS | ||
34 | help | ||
35 | Say Y here to cause the contents of a server cursor to be dumped to | ||
36 | the dmesg log if the server rotation algorithm fails to successfully | ||
37 | contact a server. | ||
38 | |||
39 | See <file:Documentation/filesystems/afs.txt> for more information. | ||
40 | |||
41 | If unsure, say N. | ||
diff --git a/fs/afs/Makefile b/fs/afs/Makefile index 546874057bd3..0738e2bf5193 100644 --- a/fs/afs/Makefile +++ b/fs/afs/Makefile | |||
@@ -17,6 +17,7 @@ kafs-y := \ | |||
17 | file.o \ | 17 | file.o \ |
18 | flock.o \ | 18 | flock.o \ |
19 | fsclient.o \ | 19 | fsclient.o \ |
20 | fs_probe.o \ | ||
20 | inode.o \ | 21 | inode.o \ |
21 | main.o \ | 22 | main.o \ |
22 | misc.o \ | 23 | misc.o \ |
@@ -29,9 +30,13 @@ kafs-y := \ | |||
29 | super.o \ | 30 | super.o \ |
30 | netdevices.o \ | 31 | netdevices.o \ |
31 | vlclient.o \ | 32 | vlclient.o \ |
33 | vl_list.o \ | ||
34 | vl_probe.o \ | ||
35 | vl_rotate.o \ | ||
32 | volume.o \ | 36 | volume.o \ |
33 | write.o \ | 37 | write.o \ |
34 | xattr.o | 38 | xattr.o \ |
39 | yfsclient.o | ||
35 | 40 | ||
36 | kafs-$(CONFIG_PROC_FS) += proc.o | 41 | kafs-$(CONFIG_PROC_FS) += proc.o |
37 | obj-$(CONFIG_AFS_FS) := kafs.o | 42 | obj-$(CONFIG_AFS_FS) := kafs.o |
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c index 55a756c60746..967db336d11a 100644 --- a/fs/afs/addr_list.c +++ b/fs/afs/addr_list.c | |||
@@ -64,19 +64,25 @@ struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, | |||
64 | /* | 64 | /* |
65 | * Parse a text string consisting of delimited addresses. | 65 | * Parse a text string consisting of delimited addresses. |
66 | */ | 66 | */ |
67 | struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | 67 | struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *net, |
68 | char delim, | 68 | const char *text, size_t len, |
69 | unsigned short service, | 69 | char delim, |
70 | unsigned short port) | 70 | unsigned short service, |
71 | unsigned short port) | ||
71 | { | 72 | { |
73 | struct afs_vlserver_list *vllist; | ||
72 | struct afs_addr_list *alist; | 74 | struct afs_addr_list *alist; |
73 | const char *p, *end = text + len; | 75 | const char *p, *end = text + len; |
76 | const char *problem; | ||
74 | unsigned int nr = 0; | 77 | unsigned int nr = 0; |
78 | int ret = -ENOMEM; | ||
75 | 79 | ||
76 | _enter("%*.*s,%c", (int)len, (int)len, text, delim); | 80 | _enter("%*.*s,%c", (int)len, (int)len, text, delim); |
77 | 81 | ||
78 | if (!len) | 82 | if (!len) { |
83 | _leave(" = -EDESTADDRREQ [empty]"); | ||
79 | return ERR_PTR(-EDESTADDRREQ); | 84 | return ERR_PTR(-EDESTADDRREQ); |
85 | } | ||
80 | 86 | ||
81 | if (delim == ':' && (memchr(text, ',', len) || !memchr(text, '.', len))) | 87 | if (delim == ':' && (memchr(text, ',', len) || !memchr(text, '.', len))) |
82 | delim = ','; | 88 | delim = ','; |
@@ -84,18 +90,24 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | |||
84 | /* Count the addresses */ | 90 | /* Count the addresses */ |
85 | p = text; | 91 | p = text; |
86 | do { | 92 | do { |
87 | if (!*p) | 93 | if (!*p) { |
88 | return ERR_PTR(-EINVAL); | 94 | problem = "nul"; |
95 | goto inval; | ||
96 | } | ||
89 | if (*p == delim) | 97 | if (*p == delim) |
90 | continue; | 98 | continue; |
91 | nr++; | 99 | nr++; |
92 | if (*p == '[') { | 100 | if (*p == '[') { |
93 | p++; | 101 | p++; |
94 | if (p == end) | 102 | if (p == end) { |
95 | return ERR_PTR(-EINVAL); | 103 | problem = "brace1"; |
104 | goto inval; | ||
105 | } | ||
96 | p = memchr(p, ']', end - p); | 106 | p = memchr(p, ']', end - p); |
97 | if (!p) | 107 | if (!p) { |
98 | return ERR_PTR(-EINVAL); | 108 | problem = "brace2"; |
109 | goto inval; | ||
110 | } | ||
99 | p++; | 111 | p++; |
100 | if (p >= end) | 112 | if (p >= end) |
101 | break; | 113 | break; |
@@ -109,10 +121,19 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | |||
109 | 121 | ||
110 | _debug("%u/%u addresses", nr, AFS_MAX_ADDRESSES); | 122 | _debug("%u/%u addresses", nr, AFS_MAX_ADDRESSES); |
111 | 123 | ||
112 | alist = afs_alloc_addrlist(nr, service, port); | 124 | vllist = afs_alloc_vlserver_list(1); |
113 | if (!alist) | 125 | if (!vllist) |
114 | return ERR_PTR(-ENOMEM); | 126 | return ERR_PTR(-ENOMEM); |
115 | 127 | ||
128 | vllist->nr_servers = 1; | ||
129 | vllist->servers[0].server = afs_alloc_vlserver("<dummy>", 7, AFS_VL_PORT); | ||
130 | if (!vllist->servers[0].server) | ||
131 | goto error_vl; | ||
132 | |||
133 | alist = afs_alloc_addrlist(nr, service, AFS_VL_PORT); | ||
134 | if (!alist) | ||
135 | goto error; | ||
136 | |||
116 | /* Extract the addresses */ | 137 | /* Extract the addresses */ |
117 | p = text; | 138 | p = text; |
118 | do { | 139 | do { |
@@ -135,17 +156,21 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | |||
135 | break; | 156 | break; |
136 | } | 157 | } |
137 | 158 | ||
138 | if (in4_pton(p, q - p, (u8 *)&x[0], -1, &stop)) | 159 | if (in4_pton(p, q - p, (u8 *)&x[0], -1, &stop)) { |
139 | family = AF_INET; | 160 | family = AF_INET; |
140 | else if (in6_pton(p, q - p, (u8 *)x, -1, &stop)) | 161 | } else if (in6_pton(p, q - p, (u8 *)x, -1, &stop)) { |
141 | family = AF_INET6; | 162 | family = AF_INET6; |
142 | else | 163 | } else { |
164 | problem = "family"; | ||
143 | goto bad_address; | 165 | goto bad_address; |
166 | } | ||
144 | 167 | ||
145 | if (stop != q) | 168 | p = q; |
169 | if (stop != p) { | ||
170 | problem = "nostop"; | ||
146 | goto bad_address; | 171 | goto bad_address; |
172 | } | ||
147 | 173 | ||
148 | p = q; | ||
149 | if (q < end && *q == ']') | 174 | if (q < end && *q == ']') |
150 | p++; | 175 | p++; |
151 | 176 | ||
@@ -154,18 +179,23 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | |||
154 | /* Port number specification "+1234" */ | 179 | /* Port number specification "+1234" */ |
155 | xport = 0; | 180 | xport = 0; |
156 | p++; | 181 | p++; |
157 | if (p >= end || !isdigit(*p)) | 182 | if (p >= end || !isdigit(*p)) { |
183 | problem = "port"; | ||
158 | goto bad_address; | 184 | goto bad_address; |
185 | } | ||
159 | do { | 186 | do { |
160 | xport *= 10; | 187 | xport *= 10; |
161 | xport += *p - '0'; | 188 | xport += *p - '0'; |
162 | if (xport > 65535) | 189 | if (xport > 65535) { |
190 | problem = "pval"; | ||
163 | goto bad_address; | 191 | goto bad_address; |
192 | } | ||
164 | p++; | 193 | p++; |
165 | } while (p < end && isdigit(*p)); | 194 | } while (p < end && isdigit(*p)); |
166 | } else if (*p == delim) { | 195 | } else if (*p == delim) { |
167 | p++; | 196 | p++; |
168 | } else { | 197 | } else { |
198 | problem = "weird"; | ||
169 | goto bad_address; | 199 | goto bad_address; |
170 | } | 200 | } |
171 | } | 201 | } |
@@ -177,12 +207,23 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | |||
177 | 207 | ||
178 | } while (p < end); | 208 | } while (p < end); |
179 | 209 | ||
210 | rcu_assign_pointer(vllist->servers[0].server->addresses, alist); | ||
180 | _leave(" = [nr %u]", alist->nr_addrs); | 211 | _leave(" = [nr %u]", alist->nr_addrs); |
181 | return alist; | 212 | return vllist; |
182 | 213 | ||
183 | bad_address: | 214 | inval: |
184 | kfree(alist); | 215 | _leave(" = -EINVAL [%s %zu %*.*s]", |
216 | problem, p - text, (int)len, (int)len, text); | ||
185 | return ERR_PTR(-EINVAL); | 217 | return ERR_PTR(-EINVAL); |
218 | bad_address: | ||
219 | _leave(" = -EINVAL [%s %zu %*.*s]", | ||
220 | problem, p - text, (int)len, (int)len, text); | ||
221 | ret = -EINVAL; | ||
222 | error: | ||
223 | afs_put_addrlist(alist); | ||
224 | error_vl: | ||
225 | afs_put_vlserverlist(net, vllist); | ||
226 | return ERR_PTR(ret); | ||
186 | } | 227 | } |
187 | 228 | ||
188 | /* | 229 | /* |
@@ -201,30 +242,34 @@ static int afs_cmp_addr_list(const struct afs_addr_list *a1, | |||
201 | /* | 242 | /* |
202 | * Perform a DNS query for VL servers and build a up an address list. | 243 | * Perform a DNS query for VL servers and build a up an address list. |
203 | */ | 244 | */ |
204 | struct afs_addr_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry) | 245 | struct afs_vlserver_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry) |
205 | { | 246 | { |
206 | struct afs_addr_list *alist; | 247 | struct afs_vlserver_list *vllist; |
207 | char *vllist = NULL; | 248 | char *result = NULL; |
208 | int ret; | 249 | int ret; |
209 | 250 | ||
210 | _enter("%s", cell->name); | 251 | _enter("%s", cell->name); |
211 | 252 | ||
212 | ret = dns_query("afsdb", cell->name, cell->name_len, | 253 | ret = dns_query("afsdb", cell->name, cell->name_len, "srv=1", |
213 | "", &vllist, _expiry); | 254 | &result, _expiry); |
214 | if (ret < 0) | 255 | if (ret < 0) { |
256 | _leave(" = %d [dns]", ret); | ||
215 | return ERR_PTR(ret); | 257 | return ERR_PTR(ret); |
216 | |||
217 | alist = afs_parse_text_addrs(vllist, strlen(vllist), ',', | ||
218 | VL_SERVICE, AFS_VL_PORT); | ||
219 | if (IS_ERR(alist)) { | ||
220 | kfree(vllist); | ||
221 | if (alist != ERR_PTR(-ENOMEM)) | ||
222 | pr_err("Failed to parse DNS data\n"); | ||
223 | return alist; | ||
224 | } | 258 | } |
225 | 259 | ||
226 | kfree(vllist); | 260 | if (*_expiry == 0) |
227 | return alist; | 261 | *_expiry = ktime_get_real_seconds() + 60; |
262 | |||
263 | if (ret > 1 && result[0] == 0) | ||
264 | vllist = afs_extract_vlserver_list(cell, result, ret); | ||
265 | else | ||
266 | vllist = afs_parse_text_addrs(cell->net, result, ret, ',', | ||
267 | VL_SERVICE, AFS_VL_PORT); | ||
268 | kfree(result); | ||
269 | if (IS_ERR(vllist) && vllist != ERR_PTR(-ENOMEM)) | ||
270 | pr_err("Failed to parse DNS data %ld\n", PTR_ERR(vllist)); | ||
271 | |||
272 | return vllist; | ||
228 | } | 273 | } |
229 | 274 | ||
230 | /* | 275 | /* |
@@ -258,6 +303,8 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port) | |||
258 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); | 303 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); |
259 | 304 | ||
260 | srx = &alist->addrs[i]; | 305 | srx = &alist->addrs[i]; |
306 | srx->srx_family = AF_RXRPC; | ||
307 | srx->transport_type = SOCK_DGRAM; | ||
261 | srx->transport_len = sizeof(srx->transport.sin); | 308 | srx->transport_len = sizeof(srx->transport.sin); |
262 | srx->transport.sin.sin_family = AF_INET; | 309 | srx->transport.sin.sin_family = AF_INET; |
263 | srx->transport.sin.sin_port = htons(port); | 310 | srx->transport.sin.sin_port = htons(port); |
@@ -296,6 +343,8 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port) | |||
296 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); | 343 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); |
297 | 344 | ||
298 | srx = &alist->addrs[i]; | 345 | srx = &alist->addrs[i]; |
346 | srx->srx_family = AF_RXRPC; | ||
347 | srx->transport_type = SOCK_DGRAM; | ||
299 | srx->transport_len = sizeof(srx->transport.sin6); | 348 | srx->transport_len = sizeof(srx->transport.sin6); |
300 | srx->transport.sin6.sin6_family = AF_INET6; | 349 | srx->transport.sin6.sin6_family = AF_INET6; |
301 | srx->transport.sin6.sin6_port = htons(port); | 350 | srx->transport.sin6.sin6_port = htons(port); |
@@ -308,25 +357,33 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port) | |||
308 | */ | 357 | */ |
309 | bool afs_iterate_addresses(struct afs_addr_cursor *ac) | 358 | bool afs_iterate_addresses(struct afs_addr_cursor *ac) |
310 | { | 359 | { |
311 | _enter("%hu+%hd", ac->start, (short)ac->index); | 360 | unsigned long set, failed; |
361 | int index; | ||
312 | 362 | ||
313 | if (!ac->alist) | 363 | if (!ac->alist) |
314 | return false; | 364 | return false; |
315 | 365 | ||
316 | if (ac->begun) { | 366 | set = ac->alist->responded; |
317 | ac->index++; | 367 | failed = ac->alist->failed; |
318 | if (ac->index == ac->alist->nr_addrs) | 368 | _enter("%lx-%lx-%lx,%d", set, failed, ac->tried, ac->index); |
319 | ac->index = 0; | ||
320 | 369 | ||
321 | if (ac->index == ac->start) { | 370 | ac->nr_iterations++; |
322 | ac->error = -EDESTADDRREQ; | 371 | |
323 | return false; | 372 | set &= ~(failed | ac->tried); |
324 | } | 373 | |
325 | } | 374 | if (!set) |
375 | return false; | ||
326 | 376 | ||
327 | ac->begun = true; | 377 | index = READ_ONCE(ac->alist->preferred); |
378 | if (test_bit(index, &set)) | ||
379 | goto selected; | ||
380 | |||
381 | index = __ffs(set); | ||
382 | |||
383 | selected: | ||
384 | ac->index = index; | ||
385 | set_bit(index, &ac->tried); | ||
328 | ac->responded = false; | 386 | ac->responded = false; |
329 | ac->addr = &ac->alist->addrs[ac->index]; | ||
330 | return true; | 387 | return true; |
331 | } | 388 | } |
332 | 389 | ||
@@ -339,53 +396,13 @@ int afs_end_cursor(struct afs_addr_cursor *ac) | |||
339 | 396 | ||
340 | alist = ac->alist; | 397 | alist = ac->alist; |
341 | if (alist) { | 398 | if (alist) { |
342 | if (ac->responded && ac->index != ac->start) | 399 | if (ac->responded && |
343 | WRITE_ONCE(alist->index, ac->index); | 400 | ac->index != alist->preferred && |
401 | test_bit(ac->alist->preferred, &ac->tried)) | ||
402 | WRITE_ONCE(alist->preferred, ac->index); | ||
344 | afs_put_addrlist(alist); | 403 | afs_put_addrlist(alist); |
404 | ac->alist = NULL; | ||
345 | } | 405 | } |
346 | 406 | ||
347 | ac->addr = NULL; | ||
348 | ac->alist = NULL; | ||
349 | ac->begun = false; | ||
350 | return ac->error; | 407 | return ac->error; |
351 | } | 408 | } |
352 | |||
353 | /* | ||
354 | * Set the address cursor for iterating over VL servers. | ||
355 | */ | ||
356 | int afs_set_vl_cursor(struct afs_addr_cursor *ac, struct afs_cell *cell) | ||
357 | { | ||
358 | struct afs_addr_list *alist; | ||
359 | int ret; | ||
360 | |||
361 | if (!rcu_access_pointer(cell->vl_addrs)) { | ||
362 | ret = wait_on_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET, | ||
363 | TASK_INTERRUPTIBLE); | ||
364 | if (ret < 0) | ||
365 | return ret; | ||
366 | |||
367 | if (!rcu_access_pointer(cell->vl_addrs) && | ||
368 | ktime_get_real_seconds() < cell->dns_expiry) | ||
369 | return cell->error; | ||
370 | } | ||
371 | |||
372 | read_lock(&cell->vl_addrs_lock); | ||
373 | alist = rcu_dereference_protected(cell->vl_addrs, | ||
374 | lockdep_is_held(&cell->vl_addrs_lock)); | ||
375 | if (alist->nr_addrs > 0) | ||
376 | afs_get_addrlist(alist); | ||
377 | else | ||
378 | alist = NULL; | ||
379 | read_unlock(&cell->vl_addrs_lock); | ||
380 | |||
381 | if (!alist) | ||
382 | return -EDESTADDRREQ; | ||
383 | |||
384 | ac->alist = alist; | ||
385 | ac->addr = NULL; | ||
386 | ac->start = READ_ONCE(alist->index); | ||
387 | ac->index = ac->start; | ||
388 | ac->error = 0; | ||
389 | ac->begun = false; | ||
390 | return 0; | ||
391 | } | ||
diff --git a/fs/afs/afs.h b/fs/afs/afs.h index b4ff1f7ae4ab..d12ffb457e47 100644 --- a/fs/afs/afs.h +++ b/fs/afs/afs.h | |||
@@ -23,9 +23,9 @@ | |||
23 | #define AFSPATHMAX 1024 /* Maximum length of a pathname plus NUL */ | 23 | #define AFSPATHMAX 1024 /* Maximum length of a pathname plus NUL */ |
24 | #define AFSOPAQUEMAX 1024 /* Maximum length of an opaque field */ | 24 | #define AFSOPAQUEMAX 1024 /* Maximum length of an opaque field */ |
25 | 25 | ||
26 | typedef unsigned afs_volid_t; | 26 | typedef u64 afs_volid_t; |
27 | typedef unsigned afs_vnodeid_t; | 27 | typedef u64 afs_vnodeid_t; |
28 | typedef unsigned long long afs_dataversion_t; | 28 | typedef u64 afs_dataversion_t; |
29 | 29 | ||
30 | typedef enum { | 30 | typedef enum { |
31 | AFSVL_RWVOL, /* read/write volume */ | 31 | AFSVL_RWVOL, /* read/write volume */ |
@@ -52,8 +52,9 @@ typedef enum { | |||
52 | */ | 52 | */ |
53 | struct afs_fid { | 53 | struct afs_fid { |
54 | afs_volid_t vid; /* volume ID */ | 54 | afs_volid_t vid; /* volume ID */ |
55 | afs_vnodeid_t vnode; /* file index within volume */ | 55 | afs_vnodeid_t vnode; /* Lower 64-bits of file index within volume */ |
56 | unsigned unique; /* unique ID number (file index version) */ | 56 | u32 vnode_hi; /* Upper 32-bits of file index */ |
57 | u32 unique; /* unique ID number (file index version) */ | ||
57 | }; | 58 | }; |
58 | 59 | ||
59 | /* | 60 | /* |
@@ -67,14 +68,14 @@ typedef enum { | |||
67 | } afs_callback_type_t; | 68 | } afs_callback_type_t; |
68 | 69 | ||
69 | struct afs_callback { | 70 | struct afs_callback { |
71 | time64_t expires_at; /* Time at which expires */ | ||
70 | unsigned version; /* Callback version */ | 72 | unsigned version; /* Callback version */ |
71 | unsigned expiry; /* Time at which expires */ | ||
72 | afs_callback_type_t type; /* Type of callback */ | 73 | afs_callback_type_t type; /* Type of callback */ |
73 | }; | 74 | }; |
74 | 75 | ||
75 | struct afs_callback_break { | 76 | struct afs_callback_break { |
76 | struct afs_fid fid; /* File identifier */ | 77 | struct afs_fid fid; /* File identifier */ |
77 | struct afs_callback cb; /* Callback details */ | 78 | //struct afs_callback cb; /* Callback details */ |
78 | }; | 79 | }; |
79 | 80 | ||
80 | #define AFSCBMAX 50 /* maximum callbacks transferred per bulk op */ | 81 | #define AFSCBMAX 50 /* maximum callbacks transferred per bulk op */ |
@@ -129,19 +130,18 @@ typedef u32 afs_access_t; | |||
129 | struct afs_file_status { | 130 | struct afs_file_status { |
130 | u64 size; /* file size */ | 131 | u64 size; /* file size */ |
131 | afs_dataversion_t data_version; /* current data version */ | 132 | afs_dataversion_t data_version; /* current data version */ |
132 | time_t mtime_client; /* last time client changed data */ | 133 | struct timespec64 mtime_client; /* Last time client changed data */ |
133 | time_t mtime_server; /* last time server changed data */ | 134 | struct timespec64 mtime_server; /* Last time server changed data */ |
134 | unsigned abort_code; /* Abort if bulk-fetching this failed */ | 135 | s64 author; /* author ID */ |
135 | 136 | s64 owner; /* owner ID */ | |
136 | afs_file_type_t type; /* file type */ | 137 | s64 group; /* group ID */ |
137 | unsigned nlink; /* link count */ | ||
138 | u32 author; /* author ID */ | ||
139 | u32 owner; /* owner ID */ | ||
140 | u32 group; /* group ID */ | ||
141 | afs_access_t caller_access; /* access rights for authenticated caller */ | 138 | afs_access_t caller_access; /* access rights for authenticated caller */ |
142 | afs_access_t anon_access; /* access rights for unauthenticated caller */ | 139 | afs_access_t anon_access; /* access rights for unauthenticated caller */ |
143 | umode_t mode; /* UNIX mode */ | 140 | umode_t mode; /* UNIX mode */ |
141 | afs_file_type_t type; /* file type */ | ||
142 | u32 nlink; /* link count */ | ||
144 | s32 lock_count; /* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */ | 143 | s32 lock_count; /* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */ |
144 | u32 abort_code; /* Abort if bulk-fetching this failed */ | ||
145 | }; | 145 | }; |
146 | 146 | ||
147 | /* | 147 | /* |
@@ -158,25 +158,27 @@ struct afs_file_status { | |||
158 | * AFS volume synchronisation information | 158 | * AFS volume synchronisation information |
159 | */ | 159 | */ |
160 | struct afs_volsync { | 160 | struct afs_volsync { |
161 | time_t creation; /* volume creation time */ | 161 | time64_t creation; /* volume creation time */ |
162 | }; | 162 | }; |
163 | 163 | ||
164 | /* | 164 | /* |
165 | * AFS volume status record | 165 | * AFS volume status record |
166 | */ | 166 | */ |
167 | struct afs_volume_status { | 167 | struct afs_volume_status { |
168 | u32 vid; /* volume ID */ | 168 | afs_volid_t vid; /* volume ID */ |
169 | u32 parent_id; /* parent volume ID */ | 169 | afs_volid_t parent_id; /* parent volume ID */ |
170 | u8 online; /* true if volume currently online and available */ | 170 | u8 online; /* true if volume currently online and available */ |
171 | u8 in_service; /* true if volume currently in service */ | 171 | u8 in_service; /* true if volume currently in service */ |
172 | u8 blessed; /* same as in_service */ | 172 | u8 blessed; /* same as in_service */ |
173 | u8 needs_salvage; /* true if consistency checking required */ | 173 | u8 needs_salvage; /* true if consistency checking required */ |
174 | u32 type; /* volume type (afs_voltype_t) */ | 174 | u32 type; /* volume type (afs_voltype_t) */ |
175 | u32 min_quota; /* minimum space set aside (blocks) */ | 175 | u64 min_quota; /* minimum space set aside (blocks) */ |
176 | u32 max_quota; /* maximum space this volume may occupy (blocks) */ | 176 | u64 max_quota; /* maximum space this volume may occupy (blocks) */ |
177 | u32 blocks_in_use; /* space this volume currently occupies (blocks) */ | 177 | u64 blocks_in_use; /* space this volume currently occupies (blocks) */ |
178 | u32 part_blocks_avail; /* space available in volume's partition */ | 178 | u64 part_blocks_avail; /* space available in volume's partition */ |
179 | u32 part_max_blocks; /* size of volume's partition */ | 179 | u64 part_max_blocks; /* size of volume's partition */ |
180 | s64 vol_copy_date; | ||
181 | s64 vol_backup_date; | ||
180 | }; | 182 | }; |
181 | 183 | ||
182 | #define AFS_BLOCK_SIZE 1024 | 184 | #define AFS_BLOCK_SIZE 1024 |
diff --git a/fs/afs/cache.c b/fs/afs/cache.c index b1c31ec4523a..f6d0a21e8052 100644 --- a/fs/afs/cache.c +++ b/fs/afs/cache.c | |||
@@ -49,7 +49,7 @@ static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, | |||
49 | struct afs_vnode *vnode = cookie_netfs_data; | 49 | struct afs_vnode *vnode = cookie_netfs_data; |
50 | struct afs_vnode_cache_aux aux; | 50 | struct afs_vnode_cache_aux aux; |
51 | 51 | ||
52 | _enter("{%x,%x,%llx},%p,%u", | 52 | _enter("{%llx,%x,%llx},%p,%u", |
53 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, | 53 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, |
54 | buffer, buflen); | 54 | buffer, buflen); |
55 | 55 | ||
diff --git a/fs/afs/callback.c b/fs/afs/callback.c index 5f261fbf2182..1c7955f5cdaf 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c | |||
@@ -210,12 +210,10 @@ void afs_init_callback_state(struct afs_server *server) | |||
210 | /* | 210 | /* |
211 | * actually break a callback | 211 | * actually break a callback |
212 | */ | 212 | */ |
213 | void afs_break_callback(struct afs_vnode *vnode) | 213 | void __afs_break_callback(struct afs_vnode *vnode) |
214 | { | 214 | { |
215 | _enter(""); | 215 | _enter(""); |
216 | 216 | ||
217 | write_seqlock(&vnode->cb_lock); | ||
218 | |||
219 | clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); | 217 | clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); |
220 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { | 218 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { |
221 | vnode->cb_break++; | 219 | vnode->cb_break++; |
@@ -230,7 +228,12 @@ void afs_break_callback(struct afs_vnode *vnode) | |||
230 | afs_lock_may_be_available(vnode); | 228 | afs_lock_may_be_available(vnode); |
231 | spin_unlock(&vnode->lock); | 229 | spin_unlock(&vnode->lock); |
232 | } | 230 | } |
231 | } | ||
233 | 232 | ||
233 | void afs_break_callback(struct afs_vnode *vnode) | ||
234 | { | ||
235 | write_seqlock(&vnode->cb_lock); | ||
236 | __afs_break_callback(vnode); | ||
234 | write_sequnlock(&vnode->cb_lock); | 237 | write_sequnlock(&vnode->cb_lock); |
235 | } | 238 | } |
236 | 239 | ||
@@ -310,14 +313,10 @@ void afs_break_callbacks(struct afs_server *server, size_t count, | |||
310 | /* TODO: Sort the callback break list by volume ID */ | 313 | /* TODO: Sort the callback break list by volume ID */ |
311 | 314 | ||
312 | for (; count > 0; callbacks++, count--) { | 315 | for (; count > 0; callbacks++, count--) { |
313 | _debug("- Fid { vl=%08x n=%u u=%u } CB { v=%u x=%u t=%u }", | 316 | _debug("- Fid { vl=%08llx n=%llu u=%u }", |
314 | callbacks->fid.vid, | 317 | callbacks->fid.vid, |
315 | callbacks->fid.vnode, | 318 | callbacks->fid.vnode, |
316 | callbacks->fid.unique, | 319 | callbacks->fid.unique); |
317 | callbacks->cb.version, | ||
318 | callbacks->cb.expiry, | ||
319 | callbacks->cb.type | ||
320 | ); | ||
321 | afs_break_one_callback(server, &callbacks->fid); | 320 | afs_break_one_callback(server, &callbacks->fid); |
322 | } | 321 | } |
323 | 322 | ||
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 6127f0fcd62c..cf445dbd5f2e 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | static unsigned __read_mostly afs_cell_gc_delay = 10; | 22 | static unsigned __read_mostly afs_cell_gc_delay = 10; |
23 | static unsigned __read_mostly afs_cell_min_ttl = 10 * 60; | ||
24 | static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60; | ||
23 | 25 | ||
24 | static void afs_manage_cell(struct work_struct *); | 26 | static void afs_manage_cell(struct work_struct *); |
25 | 27 | ||
@@ -119,7 +121,7 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net, | |||
119 | */ | 121 | */ |
120 | static struct afs_cell *afs_alloc_cell(struct afs_net *net, | 122 | static struct afs_cell *afs_alloc_cell(struct afs_net *net, |
121 | const char *name, unsigned int namelen, | 123 | const char *name, unsigned int namelen, |
122 | const char *vllist) | 124 | const char *addresses) |
123 | { | 125 | { |
124 | struct afs_cell *cell; | 126 | struct afs_cell *cell; |
125 | int i, ret; | 127 | int i, ret; |
@@ -134,7 +136,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, | |||
134 | if (namelen == 5 && memcmp(name, "@cell", 5) == 0) | 136 | if (namelen == 5 && memcmp(name, "@cell", 5) == 0) |
135 | return ERR_PTR(-EINVAL); | 137 | return ERR_PTR(-EINVAL); |
136 | 138 | ||
137 | _enter("%*.*s,%s", namelen, namelen, name, vllist); | 139 | _enter("%*.*s,%s", namelen, namelen, name, addresses); |
138 | 140 | ||
139 | cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL); | 141 | cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL); |
140 | if (!cell) { | 142 | if (!cell) { |
@@ -153,23 +155,26 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, | |||
153 | (1 << AFS_CELL_FL_NO_LOOKUP_YET)); | 155 | (1 << AFS_CELL_FL_NO_LOOKUP_YET)); |
154 | INIT_LIST_HEAD(&cell->proc_volumes); | 156 | INIT_LIST_HEAD(&cell->proc_volumes); |
155 | rwlock_init(&cell->proc_lock); | 157 | rwlock_init(&cell->proc_lock); |
156 | rwlock_init(&cell->vl_addrs_lock); | 158 | rwlock_init(&cell->vl_servers_lock); |
157 | 159 | ||
158 | /* Fill in the VL server list if we were given a list of addresses to | 160 | /* Fill in the VL server list if we were given a list of addresses to |
159 | * use. | 161 | * use. |
160 | */ | 162 | */ |
161 | if (vllist) { | 163 | if (addresses) { |
162 | struct afs_addr_list *alist; | 164 | struct afs_vlserver_list *vllist; |
163 | 165 | ||
164 | alist = afs_parse_text_addrs(vllist, strlen(vllist), ':', | 166 | vllist = afs_parse_text_addrs(net, |
165 | VL_SERVICE, AFS_VL_PORT); | 167 | addresses, strlen(addresses), ':', |
166 | if (IS_ERR(alist)) { | 168 | VL_SERVICE, AFS_VL_PORT); |
167 | ret = PTR_ERR(alist); | 169 | if (IS_ERR(vllist)) { |
170 | ret = PTR_ERR(vllist); | ||
168 | goto parse_failed; | 171 | goto parse_failed; |
169 | } | 172 | } |
170 | 173 | ||
171 | rcu_assign_pointer(cell->vl_addrs, alist); | 174 | rcu_assign_pointer(cell->vl_servers, vllist); |
172 | cell->dns_expiry = TIME64_MAX; | 175 | cell->dns_expiry = TIME64_MAX; |
176 | } else { | ||
177 | cell->dns_expiry = ktime_get_real_seconds(); | ||
173 | } | 178 | } |
174 | 179 | ||
175 | _leave(" = %p", cell); | 180 | _leave(" = %p", cell); |
@@ -356,26 +361,40 @@ int afs_cell_init(struct afs_net *net, const char *rootcell) | |||
356 | */ | 361 | */ |
357 | static void afs_update_cell(struct afs_cell *cell) | 362 | static void afs_update_cell(struct afs_cell *cell) |
358 | { | 363 | { |
359 | struct afs_addr_list *alist, *old; | 364 | struct afs_vlserver_list *vllist, *old; |
360 | time64_t now, expiry; | 365 | unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl); |
366 | unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl); | ||
367 | time64_t now, expiry = 0; | ||
361 | 368 | ||
362 | _enter("%s", cell->name); | 369 | _enter("%s", cell->name); |
363 | 370 | ||
364 | alist = afs_dns_query(cell, &expiry); | 371 | vllist = afs_dns_query(cell, &expiry); |
365 | if (IS_ERR(alist)) { | 372 | |
366 | switch (PTR_ERR(alist)) { | 373 | now = ktime_get_real_seconds(); |
374 | if (min_ttl > max_ttl) | ||
375 | max_ttl = min_ttl; | ||
376 | if (expiry < now + min_ttl) | ||
377 | expiry = now + min_ttl; | ||
378 | else if (expiry > now + max_ttl) | ||
379 | expiry = now + max_ttl; | ||
380 | |||
381 | if (IS_ERR(vllist)) { | ||
382 | switch (PTR_ERR(vllist)) { | ||
367 | case -ENODATA: | 383 | case -ENODATA: |
368 | /* The DNS said that the cell does not exist */ | 384 | case -EDESTADDRREQ: |
385 | /* The DNS said that the cell does not exist or there | ||
386 | * weren't any addresses to be had. | ||
387 | */ | ||
369 | set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags); | 388 | set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags); |
370 | clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); | 389 | clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); |
371 | cell->dns_expiry = ktime_get_real_seconds() + 61; | 390 | cell->dns_expiry = expiry; |
372 | break; | 391 | break; |
373 | 392 | ||
374 | case -EAGAIN: | 393 | case -EAGAIN: |
375 | case -ECONNREFUSED: | 394 | case -ECONNREFUSED: |
376 | default: | 395 | default: |
377 | set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); | 396 | set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); |
378 | cell->dns_expiry = ktime_get_real_seconds() + 10; | 397 | cell->dns_expiry = now + 10; |
379 | break; | 398 | break; |
380 | } | 399 | } |
381 | 400 | ||
@@ -387,12 +406,12 @@ static void afs_update_cell(struct afs_cell *cell) | |||
387 | /* Exclusion on changing vl_addrs is achieved by a | 406 | /* Exclusion on changing vl_addrs is achieved by a |
388 | * non-reentrant work item. | 407 | * non-reentrant work item. |
389 | */ | 408 | */ |
390 | old = rcu_dereference_protected(cell->vl_addrs, true); | 409 | old = rcu_dereference_protected(cell->vl_servers, true); |
391 | rcu_assign_pointer(cell->vl_addrs, alist); | 410 | rcu_assign_pointer(cell->vl_servers, vllist); |
392 | cell->dns_expiry = expiry; | 411 | cell->dns_expiry = expiry; |
393 | 412 | ||
394 | if (old) | 413 | if (old) |
395 | afs_put_addrlist(old); | 414 | afs_put_vlserverlist(cell->net, old); |
396 | } | 415 | } |
397 | 416 | ||
398 | if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags)) | 417 | if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags)) |
@@ -414,7 +433,7 @@ static void afs_cell_destroy(struct rcu_head *rcu) | |||
414 | 433 | ||
415 | ASSERTCMP(atomic_read(&cell->usage), ==, 0); | 434 | ASSERTCMP(atomic_read(&cell->usage), ==, 0); |
416 | 435 | ||
417 | afs_put_addrlist(rcu_access_pointer(cell->vl_addrs)); | 436 | afs_put_vlserverlist(cell->net, rcu_access_pointer(cell->vl_servers)); |
418 | key_put(cell->anonymous_key); | 437 | key_put(cell->anonymous_key); |
419 | kfree(cell); | 438 | kfree(cell); |
420 | 439 | ||
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 9e51d6fe7e8f..8ee5972893ed 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/ip.h> | 16 | #include <linux/ip.h> |
17 | #include "internal.h" | 17 | #include "internal.h" |
18 | #include "afs_cm.h" | 18 | #include "afs_cm.h" |
19 | #include "protocol_yfs.h" | ||
19 | 20 | ||
20 | static int afs_deliver_cb_init_call_back_state(struct afs_call *); | 21 | static int afs_deliver_cb_init_call_back_state(struct afs_call *); |
21 | static int afs_deliver_cb_init_call_back_state3(struct afs_call *); | 22 | static int afs_deliver_cb_init_call_back_state3(struct afs_call *); |
@@ -30,6 +31,8 @@ static void SRXAFSCB_Probe(struct work_struct *); | |||
30 | static void SRXAFSCB_ProbeUuid(struct work_struct *); | 31 | static void SRXAFSCB_ProbeUuid(struct work_struct *); |
31 | static void SRXAFSCB_TellMeAboutYourself(struct work_struct *); | 32 | static void SRXAFSCB_TellMeAboutYourself(struct work_struct *); |
32 | 33 | ||
34 | static int afs_deliver_yfs_cb_callback(struct afs_call *); | ||
35 | |||
33 | #define CM_NAME(name) \ | 36 | #define CM_NAME(name) \ |
34 | const char afs_SRXCB##name##_name[] __tracepoint_string = \ | 37 | const char afs_SRXCB##name##_name[] __tracepoint_string = \ |
35 | "CB." #name | 38 | "CB." #name |
@@ -101,12 +104,25 @@ static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { | |||
101 | }; | 104 | }; |
102 | 105 | ||
103 | /* | 106 | /* |
107 | * YFS CB.CallBack operation type | ||
108 | */ | ||
109 | static CM_NAME(YFS_CallBack); | ||
110 | static const struct afs_call_type afs_SRXYFSCB_CallBack = { | ||
111 | .name = afs_SRXCBYFS_CallBack_name, | ||
112 | .deliver = afs_deliver_yfs_cb_callback, | ||
113 | .destructor = afs_cm_destructor, | ||
114 | .work = SRXAFSCB_CallBack, | ||
115 | }; | ||
116 | |||
117 | /* | ||
104 | * route an incoming cache manager call | 118 | * route an incoming cache manager call |
105 | * - return T if supported, F if not | 119 | * - return T if supported, F if not |
106 | */ | 120 | */ |
107 | bool afs_cm_incoming_call(struct afs_call *call) | 121 | bool afs_cm_incoming_call(struct afs_call *call) |
108 | { | 122 | { |
109 | _enter("{CB.OP %u}", call->operation_ID); | 123 | _enter("{%u, CB.OP %u}", call->service_id, call->operation_ID); |
124 | |||
125 | call->epoch = rxrpc_kernel_get_epoch(call->net->socket, call->rxcall); | ||
110 | 126 | ||
111 | switch (call->operation_ID) { | 127 | switch (call->operation_ID) { |
112 | case CBCallBack: | 128 | case CBCallBack: |
@@ -127,12 +143,102 @@ bool afs_cm_incoming_call(struct afs_call *call) | |||
127 | case CBTellMeAboutYourself: | 143 | case CBTellMeAboutYourself: |
128 | call->type = &afs_SRXCBTellMeAboutYourself; | 144 | call->type = &afs_SRXCBTellMeAboutYourself; |
129 | return true; | 145 | return true; |
146 | case YFSCBCallBack: | ||
147 | if (call->service_id != YFS_CM_SERVICE) | ||
148 | return false; | ||
149 | call->type = &afs_SRXYFSCB_CallBack; | ||
150 | return true; | ||
130 | default: | 151 | default: |
131 | return false; | 152 | return false; |
132 | } | 153 | } |
133 | } | 154 | } |
134 | 155 | ||
135 | /* | 156 | /* |
157 | * Record a probe to the cache manager from a server. | ||
158 | */ | ||
159 | static int afs_record_cm_probe(struct afs_call *call, struct afs_server *server) | ||
160 | { | ||
161 | _enter(""); | ||
162 | |||
163 | if (test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags) && | ||
164 | !test_bit(AFS_SERVER_FL_PROBING, &server->flags)) { | ||
165 | if (server->cm_epoch == call->epoch) | ||
166 | return 0; | ||
167 | |||
168 | if (!server->probe.said_rebooted) { | ||
169 | pr_notice("kAFS: FS rebooted %pU\n", &server->uuid); | ||
170 | server->probe.said_rebooted = true; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | spin_lock(&server->probe_lock); | ||
175 | |||
176 | if (!test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags)) { | ||
177 | server->cm_epoch = call->epoch; | ||
178 | server->probe.cm_epoch = call->epoch; | ||
179 | goto out; | ||
180 | } | ||
181 | |||
182 | if (server->probe.cm_probed && | ||
183 | call->epoch != server->probe.cm_epoch && | ||
184 | !server->probe.said_inconsistent) { | ||
185 | pr_notice("kAFS: FS endpoints inconsistent %pU\n", | ||
186 | &server->uuid); | ||
187 | server->probe.said_inconsistent = true; | ||
188 | } | ||
189 | |||
190 | if (!server->probe.cm_probed || call->epoch == server->cm_epoch) | ||
191 | server->probe.cm_epoch = server->cm_epoch; | ||
192 | |||
193 | out: | ||
194 | server->probe.cm_probed = true; | ||
195 | spin_unlock(&server->probe_lock); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * Find the server record by peer address and record a probe to the cache | ||
201 | * manager from a server. | ||
202 | */ | ||
203 | static int afs_find_cm_server_by_peer(struct afs_call *call) | ||
204 | { | ||
205 | struct sockaddr_rxrpc srx; | ||
206 | struct afs_server *server; | ||
207 | |||
208 | rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); | ||
209 | |||
210 | server = afs_find_server(call->net, &srx); | ||
211 | if (!server) { | ||
212 | trace_afs_cm_no_server(call, &srx); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | call->cm_server = server; | ||
217 | return afs_record_cm_probe(call, server); | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * Find the server record by server UUID and record a probe to the cache | ||
222 | * manager from a server. | ||
223 | */ | ||
224 | static int afs_find_cm_server_by_uuid(struct afs_call *call, | ||
225 | struct afs_uuid *uuid) | ||
226 | { | ||
227 | struct afs_server *server; | ||
228 | |||
229 | rcu_read_lock(); | ||
230 | server = afs_find_server_by_uuid(call->net, call->request); | ||
231 | rcu_read_unlock(); | ||
232 | if (!server) { | ||
233 | trace_afs_cm_no_server_u(call, call->request); | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | call->cm_server = server; | ||
238 | return afs_record_cm_probe(call, server); | ||
239 | } | ||
240 | |||
241 | /* | ||
136 | * Clean up a cache manager call. | 242 | * Clean up a cache manager call. |
137 | */ | 243 | */ |
138 | static void afs_cm_destructor(struct afs_call *call) | 244 | static void afs_cm_destructor(struct afs_call *call) |
@@ -168,7 +274,6 @@ static void SRXAFSCB_CallBack(struct work_struct *work) | |||
168 | static int afs_deliver_cb_callback(struct afs_call *call) | 274 | static int afs_deliver_cb_callback(struct afs_call *call) |
169 | { | 275 | { |
170 | struct afs_callback_break *cb; | 276 | struct afs_callback_break *cb; |
171 | struct sockaddr_rxrpc srx; | ||
172 | __be32 *bp; | 277 | __be32 *bp; |
173 | int ret, loop; | 278 | int ret, loop; |
174 | 279 | ||
@@ -176,32 +281,32 @@ static int afs_deliver_cb_callback(struct afs_call *call) | |||
176 | 281 | ||
177 | switch (call->unmarshall) { | 282 | switch (call->unmarshall) { |
178 | case 0: | 283 | case 0: |
179 | call->offset = 0; | 284 | afs_extract_to_tmp(call); |
180 | call->unmarshall++; | 285 | call->unmarshall++; |
181 | 286 | ||
182 | /* extract the FID array and its count in two steps */ | 287 | /* extract the FID array and its count in two steps */ |
183 | case 1: | 288 | case 1: |
184 | _debug("extract FID count"); | 289 | _debug("extract FID count"); |
185 | ret = afs_extract_data(call, &call->tmp, 4, true); | 290 | ret = afs_extract_data(call, true); |
186 | if (ret < 0) | 291 | if (ret < 0) |
187 | return ret; | 292 | return ret; |
188 | 293 | ||
189 | call->count = ntohl(call->tmp); | 294 | call->count = ntohl(call->tmp); |
190 | _debug("FID count: %u", call->count); | 295 | _debug("FID count: %u", call->count); |
191 | if (call->count > AFSCBMAX) | 296 | if (call->count > AFSCBMAX) |
192 | return afs_protocol_error(call, -EBADMSG); | 297 | return afs_protocol_error(call, -EBADMSG, |
298 | afs_eproto_cb_fid_count); | ||
193 | 299 | ||
194 | call->buffer = kmalloc(array3_size(call->count, 3, 4), | 300 | call->buffer = kmalloc(array3_size(call->count, 3, 4), |
195 | GFP_KERNEL); | 301 | GFP_KERNEL); |
196 | if (!call->buffer) | 302 | if (!call->buffer) |
197 | return -ENOMEM; | 303 | return -ENOMEM; |
198 | call->offset = 0; | 304 | afs_extract_to_buf(call, call->count * 3 * 4); |
199 | call->unmarshall++; | 305 | call->unmarshall++; |
200 | 306 | ||
201 | case 2: | 307 | case 2: |
202 | _debug("extract FID array"); | 308 | _debug("extract FID array"); |
203 | ret = afs_extract_data(call, call->buffer, | 309 | ret = afs_extract_data(call, true); |
204 | call->count * 3 * 4, true); | ||
205 | if (ret < 0) | 310 | if (ret < 0) |
206 | return ret; | 311 | return ret; |
207 | 312 | ||
@@ -218,59 +323,46 @@ static int afs_deliver_cb_callback(struct afs_call *call) | |||
218 | cb->fid.vid = ntohl(*bp++); | 323 | cb->fid.vid = ntohl(*bp++); |
219 | cb->fid.vnode = ntohl(*bp++); | 324 | cb->fid.vnode = ntohl(*bp++); |
220 | cb->fid.unique = ntohl(*bp++); | 325 | cb->fid.unique = ntohl(*bp++); |
221 | cb->cb.type = AFSCM_CB_UNTYPED; | ||
222 | } | 326 | } |
223 | 327 | ||
224 | call->offset = 0; | 328 | afs_extract_to_tmp(call); |
225 | call->unmarshall++; | 329 | call->unmarshall++; |
226 | 330 | ||
227 | /* extract the callback array and its count in two steps */ | 331 | /* extract the callback array and its count in two steps */ |
228 | case 3: | 332 | case 3: |
229 | _debug("extract CB count"); | 333 | _debug("extract CB count"); |
230 | ret = afs_extract_data(call, &call->tmp, 4, true); | 334 | ret = afs_extract_data(call, true); |
231 | if (ret < 0) | 335 | if (ret < 0) |
232 | return ret; | 336 | return ret; |
233 | 337 | ||
234 | call->count2 = ntohl(call->tmp); | 338 | call->count2 = ntohl(call->tmp); |
235 | _debug("CB count: %u", call->count2); | 339 | _debug("CB count: %u", call->count2); |
236 | if (call->count2 != call->count && call->count2 != 0) | 340 | if (call->count2 != call->count && call->count2 != 0) |
237 | return afs_protocol_error(call, -EBADMSG); | 341 | return afs_protocol_error(call, -EBADMSG, |
238 | call->offset = 0; | 342 | afs_eproto_cb_count); |
343 | call->_iter = &call->iter; | ||
344 | iov_iter_discard(&call->iter, READ, call->count2 * 3 * 4); | ||
239 | call->unmarshall++; | 345 | call->unmarshall++; |
240 | 346 | ||
241 | case 4: | 347 | case 4: |
242 | _debug("extract CB array"); | 348 | _debug("extract discard %zu/%u", |
243 | ret = afs_extract_data(call, call->buffer, | 349 | iov_iter_count(&call->iter), call->count2 * 3 * 4); |
244 | call->count2 * 3 * 4, false); | 350 | |
351 | ret = afs_extract_data(call, false); | ||
245 | if (ret < 0) | 352 | if (ret < 0) |
246 | return ret; | 353 | return ret; |
247 | 354 | ||
248 | _debug("unmarshall CB array"); | ||
249 | cb = call->request; | ||
250 | bp = call->buffer; | ||
251 | for (loop = call->count2; loop > 0; loop--, cb++) { | ||
252 | cb->cb.version = ntohl(*bp++); | ||
253 | cb->cb.expiry = ntohl(*bp++); | ||
254 | cb->cb.type = ntohl(*bp++); | ||
255 | } | ||
256 | |||
257 | call->offset = 0; | ||
258 | call->unmarshall++; | 355 | call->unmarshall++; |
259 | case 5: | 356 | case 5: |
260 | break; | 357 | break; |
261 | } | 358 | } |
262 | 359 | ||
263 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) | 360 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) |
264 | return -EIO; | 361 | return afs_io_error(call, afs_io_error_cm_reply); |
265 | 362 | ||
266 | /* we'll need the file server record as that tells us which set of | 363 | /* we'll need the file server record as that tells us which set of |
267 | * vnodes to operate upon */ | 364 | * vnodes to operate upon */ |
268 | rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); | 365 | return afs_find_cm_server_by_peer(call); |
269 | call->cm_server = afs_find_server(call->net, &srx); | ||
270 | if (!call->cm_server) | ||
271 | trace_afs_cm_no_server(call, &srx); | ||
272 | |||
273 | return afs_queue_call_work(call); | ||
274 | } | 366 | } |
275 | 367 | ||
276 | /* | 368 | /* |
@@ -294,24 +386,18 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work) | |||
294 | */ | 386 | */ |
295 | static int afs_deliver_cb_init_call_back_state(struct afs_call *call) | 387 | static int afs_deliver_cb_init_call_back_state(struct afs_call *call) |
296 | { | 388 | { |
297 | struct sockaddr_rxrpc srx; | ||
298 | int ret; | 389 | int ret; |
299 | 390 | ||
300 | _enter(""); | 391 | _enter(""); |
301 | 392 | ||
302 | rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); | 393 | afs_extract_discard(call, 0); |
303 | 394 | ret = afs_extract_data(call, false); | |
304 | ret = afs_extract_data(call, NULL, 0, false); | ||
305 | if (ret < 0) | 395 | if (ret < 0) |
306 | return ret; | 396 | return ret; |
307 | 397 | ||
308 | /* we'll need the file server record as that tells us which set of | 398 | /* we'll need the file server record as that tells us which set of |
309 | * vnodes to operate upon */ | 399 | * vnodes to operate upon */ |
310 | call->cm_server = afs_find_server(call->net, &srx); | 400 | return afs_find_cm_server_by_peer(call); |
311 | if (!call->cm_server) | ||
312 | trace_afs_cm_no_server(call, &srx); | ||
313 | |||
314 | return afs_queue_call_work(call); | ||
315 | } | 401 | } |
316 | 402 | ||
317 | /* | 403 | /* |
@@ -330,16 +416,15 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) | |||
330 | 416 | ||
331 | switch (call->unmarshall) { | 417 | switch (call->unmarshall) { |
332 | case 0: | 418 | case 0: |
333 | call->offset = 0; | ||
334 | call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); | 419 | call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); |
335 | if (!call->buffer) | 420 | if (!call->buffer) |
336 | return -ENOMEM; | 421 | return -ENOMEM; |
422 | afs_extract_to_buf(call, 11 * sizeof(__be32)); | ||
337 | call->unmarshall++; | 423 | call->unmarshall++; |
338 | 424 | ||
339 | case 1: | 425 | case 1: |
340 | _debug("extract UUID"); | 426 | _debug("extract UUID"); |
341 | ret = afs_extract_data(call, call->buffer, | 427 | ret = afs_extract_data(call, false); |
342 | 11 * sizeof(__be32), false); | ||
343 | switch (ret) { | 428 | switch (ret) { |
344 | case 0: break; | 429 | case 0: break; |
345 | case -EAGAIN: return 0; | 430 | case -EAGAIN: return 0; |
@@ -362,7 +447,6 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) | |||
362 | for (loop = 0; loop < 6; loop++) | 447 | for (loop = 0; loop < 6; loop++) |
363 | r->node[loop] = ntohl(b[loop + 5]); | 448 | r->node[loop] = ntohl(b[loop + 5]); |
364 | 449 | ||
365 | call->offset = 0; | ||
366 | call->unmarshall++; | 450 | call->unmarshall++; |
367 | 451 | ||
368 | case 2: | 452 | case 2: |
@@ -370,17 +454,11 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) | |||
370 | } | 454 | } |
371 | 455 | ||
372 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) | 456 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) |
373 | return -EIO; | 457 | return afs_io_error(call, afs_io_error_cm_reply); |
374 | 458 | ||
375 | /* we'll need the file server record as that tells us which set of | 459 | /* we'll need the file server record as that tells us which set of |
376 | * vnodes to operate upon */ | 460 | * vnodes to operate upon */ |
377 | rcu_read_lock(); | 461 | return afs_find_cm_server_by_uuid(call, call->request); |
378 | call->cm_server = afs_find_server_by_uuid(call->net, call->request); | ||
379 | rcu_read_unlock(); | ||
380 | if (!call->cm_server) | ||
381 | trace_afs_cm_no_server_u(call, call->request); | ||
382 | |||
383 | return afs_queue_call_work(call); | ||
384 | } | 462 | } |
385 | 463 | ||
386 | /* | 464 | /* |
@@ -405,14 +483,14 @@ static int afs_deliver_cb_probe(struct afs_call *call) | |||
405 | 483 | ||
406 | _enter(""); | 484 | _enter(""); |
407 | 485 | ||
408 | ret = afs_extract_data(call, NULL, 0, false); | 486 | afs_extract_discard(call, 0); |
487 | ret = afs_extract_data(call, false); | ||
409 | if (ret < 0) | 488 | if (ret < 0) |
410 | return ret; | 489 | return ret; |
411 | 490 | ||
412 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) | 491 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) |
413 | return -EIO; | 492 | return afs_io_error(call, afs_io_error_cm_reply); |
414 | 493 | return afs_find_cm_server_by_peer(call); | |
415 | return afs_queue_call_work(call); | ||
416 | } | 494 | } |
417 | 495 | ||
418 | /* | 496 | /* |
@@ -453,16 +531,15 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) | |||
453 | 531 | ||
454 | switch (call->unmarshall) { | 532 | switch (call->unmarshall) { |
455 | case 0: | 533 | case 0: |
456 | call->offset = 0; | ||
457 | call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); | 534 | call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); |
458 | if (!call->buffer) | 535 | if (!call->buffer) |
459 | return -ENOMEM; | 536 | return -ENOMEM; |
537 | afs_extract_to_buf(call, 11 * sizeof(__be32)); | ||
460 | call->unmarshall++; | 538 | call->unmarshall++; |
461 | 539 | ||
462 | case 1: | 540 | case 1: |
463 | _debug("extract UUID"); | 541 | _debug("extract UUID"); |
464 | ret = afs_extract_data(call, call->buffer, | 542 | ret = afs_extract_data(call, false); |
465 | 11 * sizeof(__be32), false); | ||
466 | switch (ret) { | 543 | switch (ret) { |
467 | case 0: break; | 544 | case 0: break; |
468 | case -EAGAIN: return 0; | 545 | case -EAGAIN: return 0; |
@@ -485,7 +562,6 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) | |||
485 | for (loop = 0; loop < 6; loop++) | 562 | for (loop = 0; loop < 6; loop++) |
486 | r->node[loop] = ntohl(b[loop + 5]); | 563 | r->node[loop] = ntohl(b[loop + 5]); |
487 | 564 | ||
488 | call->offset = 0; | ||
489 | call->unmarshall++; | 565 | call->unmarshall++; |
490 | 566 | ||
491 | case 2: | 567 | case 2: |
@@ -493,9 +569,8 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) | |||
493 | } | 569 | } |
494 | 570 | ||
495 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) | 571 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) |
496 | return -EIO; | 572 | return afs_io_error(call, afs_io_error_cm_reply); |
497 | 573 | return afs_find_cm_server_by_uuid(call, call->request); | |
498 | return afs_queue_call_work(call); | ||
499 | } | 574 | } |
500 | 575 | ||
501 | /* | 576 | /* |
@@ -570,12 +645,88 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call) | |||
570 | 645 | ||
571 | _enter(""); | 646 | _enter(""); |
572 | 647 | ||
573 | ret = afs_extract_data(call, NULL, 0, false); | 648 | afs_extract_discard(call, 0); |
649 | ret = afs_extract_data(call, false); | ||
574 | if (ret < 0) | 650 | if (ret < 0) |
575 | return ret; | 651 | return ret; |
576 | 652 | ||
577 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) | 653 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) |
578 | return -EIO; | 654 | return afs_io_error(call, afs_io_error_cm_reply); |
655 | return afs_find_cm_server_by_peer(call); | ||
656 | } | ||
657 | |||
658 | /* | ||
659 | * deliver request data to a YFS CB.CallBack call | ||
660 | */ | ||
661 | static int afs_deliver_yfs_cb_callback(struct afs_call *call) | ||
662 | { | ||
663 | struct afs_callback_break *cb; | ||
664 | struct yfs_xdr_YFSFid *bp; | ||
665 | size_t size; | ||
666 | int ret, loop; | ||
667 | |||
668 | _enter("{%u}", call->unmarshall); | ||
669 | |||
670 | switch (call->unmarshall) { | ||
671 | case 0: | ||
672 | afs_extract_to_tmp(call); | ||
673 | call->unmarshall++; | ||
674 | |||
675 | /* extract the FID array and its count in two steps */ | ||
676 | case 1: | ||
677 | _debug("extract FID count"); | ||
678 | ret = afs_extract_data(call, true); | ||
679 | if (ret < 0) | ||
680 | return ret; | ||
681 | |||
682 | call->count = ntohl(call->tmp); | ||
683 | _debug("FID count: %u", call->count); | ||
684 | if (call->count > YFSCBMAX) | ||
685 | return afs_protocol_error(call, -EBADMSG, | ||
686 | afs_eproto_cb_fid_count); | ||
687 | |||
688 | size = array_size(call->count, sizeof(struct yfs_xdr_YFSFid)); | ||
689 | call->buffer = kmalloc(size, GFP_KERNEL); | ||
690 | if (!call->buffer) | ||
691 | return -ENOMEM; | ||
692 | afs_extract_to_buf(call, size); | ||
693 | call->unmarshall++; | ||
694 | |||
695 | case 2: | ||
696 | _debug("extract FID array"); | ||
697 | ret = afs_extract_data(call, false); | ||
698 | if (ret < 0) | ||
699 | return ret; | ||
700 | |||
701 | _debug("unmarshall FID array"); | ||
702 | call->request = kcalloc(call->count, | ||
703 | sizeof(struct afs_callback_break), | ||
704 | GFP_KERNEL); | ||
705 | if (!call->request) | ||
706 | return -ENOMEM; | ||
707 | |||
708 | cb = call->request; | ||
709 | bp = call->buffer; | ||
710 | for (loop = call->count; loop > 0; loop--, cb++) { | ||
711 | cb->fid.vid = xdr_to_u64(bp->volume); | ||
712 | cb->fid.vnode = xdr_to_u64(bp->vnode.lo); | ||
713 | cb->fid.vnode_hi = ntohl(bp->vnode.hi); | ||
714 | cb->fid.unique = ntohl(bp->vnode.unique); | ||
715 | bp++; | ||
716 | } | ||
717 | |||
718 | afs_extract_to_tmp(call); | ||
719 | call->unmarshall++; | ||
720 | |||
721 | case 3: | ||
722 | break; | ||
723 | } | ||
724 | |||
725 | if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) | ||
726 | return afs_io_error(call, afs_io_error_cm_reply); | ||
579 | 727 | ||
580 | return afs_queue_call_work(call); | 728 | /* We'll need the file server record as that tells us which set of |
729 | * vnodes to operate upon. | ||
730 | */ | ||
731 | return afs_find_cm_server_by_peer(call); | ||
581 | } | 732 | } |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 855bf2b79fed..43dea3b00c29 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -138,6 +138,7 @@ static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page, | |||
138 | ntohs(dbuf->blocks[tmp].hdr.magic)); | 138 | ntohs(dbuf->blocks[tmp].hdr.magic)); |
139 | trace_afs_dir_check_failed(dvnode, off, i_size); | 139 | trace_afs_dir_check_failed(dvnode, off, i_size); |
140 | kunmap(page); | 140 | kunmap(page); |
141 | trace_afs_file_error(dvnode, -EIO, afs_file_error_dir_bad_magic); | ||
141 | goto error; | 142 | goto error; |
142 | } | 143 | } |
143 | 144 | ||
@@ -190,9 +191,11 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) | |||
190 | retry: | 191 | retry: |
191 | i_size = i_size_read(&dvnode->vfs_inode); | 192 | i_size = i_size_read(&dvnode->vfs_inode); |
192 | if (i_size < 2048) | 193 | if (i_size < 2048) |
193 | return ERR_PTR(-EIO); | 194 | return ERR_PTR(afs_bad(dvnode, afs_file_error_dir_small)); |
194 | if (i_size > 2048 * 1024) | 195 | if (i_size > 2048 * 1024) { |
196 | trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big); | ||
195 | return ERR_PTR(-EFBIG); | 197 | return ERR_PTR(-EFBIG); |
198 | } | ||
196 | 199 | ||
197 | _enter("%llu", i_size); | 200 | _enter("%llu", i_size); |
198 | 201 | ||
@@ -315,7 +318,8 @@ content_has_grown: | |||
315 | /* | 318 | /* |
316 | * deal with one block in an AFS directory | 319 | * deal with one block in an AFS directory |
317 | */ | 320 | */ |
318 | static int afs_dir_iterate_block(struct dir_context *ctx, | 321 | static int afs_dir_iterate_block(struct afs_vnode *dvnode, |
322 | struct dir_context *ctx, | ||
319 | union afs_xdr_dir_block *block, | 323 | union afs_xdr_dir_block *block, |
320 | unsigned blkoff) | 324 | unsigned blkoff) |
321 | { | 325 | { |
@@ -365,7 +369,7 @@ static int afs_dir_iterate_block(struct dir_context *ctx, | |||
365 | " (len %u/%zu)", | 369 | " (len %u/%zu)", |
366 | blkoff / sizeof(union afs_xdr_dir_block), | 370 | blkoff / sizeof(union afs_xdr_dir_block), |
367 | offset, next, tmp, nlen); | 371 | offset, next, tmp, nlen); |
368 | return -EIO; | 372 | return afs_bad(dvnode, afs_file_error_dir_over_end); |
369 | } | 373 | } |
370 | if (!(block->hdr.bitmap[next / 8] & | 374 | if (!(block->hdr.bitmap[next / 8] & |
371 | (1 << (next % 8)))) { | 375 | (1 << (next % 8)))) { |
@@ -373,7 +377,7 @@ static int afs_dir_iterate_block(struct dir_context *ctx, | |||
373 | " %u unmarked extension (len %u/%zu)", | 377 | " %u unmarked extension (len %u/%zu)", |
374 | blkoff / sizeof(union afs_xdr_dir_block), | 378 | blkoff / sizeof(union afs_xdr_dir_block), |
375 | offset, next, tmp, nlen); | 379 | offset, next, tmp, nlen); |
376 | return -EIO; | 380 | return afs_bad(dvnode, afs_file_error_dir_unmarked_ext); |
377 | } | 381 | } |
378 | 382 | ||
379 | _debug("ENT[%zu.%u]: ext %u/%zu", | 383 | _debug("ENT[%zu.%u]: ext %u/%zu", |
@@ -442,7 +446,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, | |||
442 | */ | 446 | */ |
443 | page = req->pages[blkoff / PAGE_SIZE]; | 447 | page = req->pages[blkoff / PAGE_SIZE]; |
444 | if (!page) { | 448 | if (!page) { |
445 | ret = -EIO; | 449 | ret = afs_bad(dvnode, afs_file_error_dir_missing_page); |
446 | break; | 450 | break; |
447 | } | 451 | } |
448 | mark_page_accessed(page); | 452 | mark_page_accessed(page); |
@@ -455,7 +459,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, | |||
455 | do { | 459 | do { |
456 | dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) / | 460 | dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) / |
457 | sizeof(union afs_xdr_dir_block)]; | 461 | sizeof(union afs_xdr_dir_block)]; |
458 | ret = afs_dir_iterate_block(ctx, dblock, blkoff); | 462 | ret = afs_dir_iterate_block(dvnode, ctx, dblock, blkoff); |
459 | if (ret != 1) { | 463 | if (ret != 1) { |
460 | kunmap(page); | 464 | kunmap(page); |
461 | goto out; | 465 | goto out; |
@@ -548,7 +552,7 @@ static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry, | |||
548 | } | 552 | } |
549 | 553 | ||
550 | *fid = cookie.fid; | 554 | *fid = cookie.fid; |
551 | _leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique); | 555 | _leave(" = 0 { vn=%llu u=%u }", fid->vnode, fid->unique); |
552 | return 0; | 556 | return 0; |
553 | } | 557 | } |
554 | 558 | ||
@@ -826,7 +830,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
826 | struct key *key; | 830 | struct key *key; |
827 | int ret; | 831 | int ret; |
828 | 832 | ||
829 | _enter("{%x:%u},%p{%pd},", | 833 | _enter("{%llx:%llu},%p{%pd},", |
830 | dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry); | 834 | dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry); |
831 | 835 | ||
832 | ASSERTCMP(d_inode(dentry), ==, NULL); | 836 | ASSERTCMP(d_inode(dentry), ==, NULL); |
@@ -896,7 +900,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) | |||
896 | 900 | ||
897 | if (d_really_is_positive(dentry)) { | 901 | if (d_really_is_positive(dentry)) { |
898 | vnode = AFS_FS_I(d_inode(dentry)); | 902 | vnode = AFS_FS_I(d_inode(dentry)); |
899 | _enter("{v={%x:%u} n=%pd fl=%lx},", | 903 | _enter("{v={%llx:%llu} n=%pd fl=%lx},", |
900 | vnode->fid.vid, vnode->fid.vnode, dentry, | 904 | vnode->fid.vid, vnode->fid.vnode, dentry, |
901 | vnode->flags); | 905 | vnode->flags); |
902 | } else { | 906 | } else { |
@@ -965,7 +969,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) | |||
965 | /* if the vnode ID has changed, then the dirent points to a | 969 | /* if the vnode ID has changed, then the dirent points to a |
966 | * different file */ | 970 | * different file */ |
967 | if (fid.vnode != vnode->fid.vnode) { | 971 | if (fid.vnode != vnode->fid.vnode) { |
968 | _debug("%pd: dirent changed [%u != %u]", | 972 | _debug("%pd: dirent changed [%llu != %llu]", |
969 | dentry, fid.vnode, | 973 | dentry, fid.vnode, |
970 | vnode->fid.vnode); | 974 | vnode->fid.vnode); |
971 | goto not_found; | 975 | goto not_found; |
@@ -1085,6 +1089,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc, | |||
1085 | 1089 | ||
1086 | vnode = AFS_FS_I(inode); | 1090 | vnode = AFS_FS_I(inode); |
1087 | set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); | 1091 | set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); |
1092 | afs_vnode_commit_status(fc, vnode, 0); | ||
1088 | d_add(new_dentry, inode); | 1093 | d_add(new_dentry, inode); |
1089 | } | 1094 | } |
1090 | 1095 | ||
@@ -1104,7 +1109,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1104 | 1109 | ||
1105 | mode |= S_IFDIR; | 1110 | mode |= S_IFDIR; |
1106 | 1111 | ||
1107 | _enter("{%x:%u},{%pd},%ho", | 1112 | _enter("{%llx:%llu},{%pd},%ho", |
1108 | dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); | 1113 | dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); |
1109 | 1114 | ||
1110 | key = afs_request_key(dvnode->volume->cell); | 1115 | key = afs_request_key(dvnode->volume->cell); |
@@ -1169,12 +1174,12 @@ static void afs_dir_remove_subdir(struct dentry *dentry) | |||
1169 | static int afs_rmdir(struct inode *dir, struct dentry *dentry) | 1174 | static int afs_rmdir(struct inode *dir, struct dentry *dentry) |
1170 | { | 1175 | { |
1171 | struct afs_fs_cursor fc; | 1176 | struct afs_fs_cursor fc; |
1172 | struct afs_vnode *dvnode = AFS_FS_I(dir); | 1177 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; |
1173 | struct key *key; | 1178 | struct key *key; |
1174 | u64 data_version = dvnode->status.data_version; | 1179 | u64 data_version = dvnode->status.data_version; |
1175 | int ret; | 1180 | int ret; |
1176 | 1181 | ||
1177 | _enter("{%x:%u},{%pd}", | 1182 | _enter("{%llx:%llu},{%pd}", |
1178 | dvnode->fid.vid, dvnode->fid.vnode, dentry); | 1183 | dvnode->fid.vid, dvnode->fid.vnode, dentry); |
1179 | 1184 | ||
1180 | key = afs_request_key(dvnode->volume->cell); | 1185 | key = afs_request_key(dvnode->volume->cell); |
@@ -1183,11 +1188,19 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1183 | goto error; | 1188 | goto error; |
1184 | } | 1189 | } |
1185 | 1190 | ||
1191 | /* Try to make sure we have a callback promise on the victim. */ | ||
1192 | if (d_really_is_positive(dentry)) { | ||
1193 | vnode = AFS_FS_I(d_inode(dentry)); | ||
1194 | ret = afs_validate(vnode, key); | ||
1195 | if (ret < 0) | ||
1196 | goto error_key; | ||
1197 | } | ||
1198 | |||
1186 | ret = -ERESTARTSYS; | 1199 | ret = -ERESTARTSYS; |
1187 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { | 1200 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { |
1188 | while (afs_select_fileserver(&fc)) { | 1201 | while (afs_select_fileserver(&fc)) { |
1189 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1202 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
1190 | afs_fs_remove(&fc, dentry->d_name.name, true, | 1203 | afs_fs_remove(&fc, vnode, dentry->d_name.name, true, |
1191 | data_version); | 1204 | data_version); |
1192 | } | 1205 | } |
1193 | 1206 | ||
@@ -1201,6 +1214,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1201 | } | 1214 | } |
1202 | } | 1215 | } |
1203 | 1216 | ||
1217 | error_key: | ||
1204 | key_put(key); | 1218 | key_put(key); |
1205 | error: | 1219 | error: |
1206 | return ret; | 1220 | return ret; |
@@ -1231,7 +1245,9 @@ static int afs_dir_remove_link(struct dentry *dentry, struct key *key, | |||
1231 | if (d_really_is_positive(dentry)) { | 1245 | if (d_really_is_positive(dentry)) { |
1232 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); | 1246 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); |
1233 | 1247 | ||
1234 | if (dir_valid) { | 1248 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { |
1249 | /* Already done */ | ||
1250 | } else if (dir_valid) { | ||
1235 | drop_nlink(&vnode->vfs_inode); | 1251 | drop_nlink(&vnode->vfs_inode); |
1236 | if (vnode->vfs_inode.i_nlink == 0) { | 1252 | if (vnode->vfs_inode.i_nlink == 0) { |
1237 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | 1253 | set_bit(AFS_VNODE_DELETED, &vnode->flags); |
@@ -1260,13 +1276,13 @@ static int afs_dir_remove_link(struct dentry *dentry, struct key *key, | |||
1260 | static int afs_unlink(struct inode *dir, struct dentry *dentry) | 1276 | static int afs_unlink(struct inode *dir, struct dentry *dentry) |
1261 | { | 1277 | { |
1262 | struct afs_fs_cursor fc; | 1278 | struct afs_fs_cursor fc; |
1263 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode; | 1279 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; |
1264 | struct key *key; | 1280 | struct key *key; |
1265 | unsigned long d_version = (unsigned long)dentry->d_fsdata; | 1281 | unsigned long d_version = (unsigned long)dentry->d_fsdata; |
1266 | u64 data_version = dvnode->status.data_version; | 1282 | u64 data_version = dvnode->status.data_version; |
1267 | int ret; | 1283 | int ret; |
1268 | 1284 | ||
1269 | _enter("{%x:%u},{%pd}", | 1285 | _enter("{%llx:%llu},{%pd}", |
1270 | dvnode->fid.vid, dvnode->fid.vnode, dentry); | 1286 | dvnode->fid.vid, dvnode->fid.vnode, dentry); |
1271 | 1287 | ||
1272 | if (dentry->d_name.len >= AFSNAMEMAX) | 1288 | if (dentry->d_name.len >= AFSNAMEMAX) |
@@ -1290,7 +1306,18 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) | |||
1290 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { | 1306 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { |
1291 | while (afs_select_fileserver(&fc)) { | 1307 | while (afs_select_fileserver(&fc)) { |
1292 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1308 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
1293 | afs_fs_remove(&fc, dentry->d_name.name, false, | 1309 | |
1310 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) && | ||
1311 | !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) { | ||
1312 | yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name, | ||
1313 | data_version); | ||
1314 | if (fc.ac.error != -ECONNABORTED || | ||
1315 | fc.ac.abort_code != RXGEN_OPCODE) | ||
1316 | continue; | ||
1317 | set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags); | ||
1318 | } | ||
1319 | |||
1320 | afs_fs_remove(&fc, vnode, dentry->d_name.name, false, | ||
1294 | data_version); | 1321 | data_version); |
1295 | } | 1322 | } |
1296 | 1323 | ||
@@ -1330,7 +1357,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
1330 | 1357 | ||
1331 | mode |= S_IFREG; | 1358 | mode |= S_IFREG; |
1332 | 1359 | ||
1333 | _enter("{%x:%u},{%pd},%ho,", | 1360 | _enter("{%llx:%llu},{%pd},%ho,", |
1334 | dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); | 1361 | dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); |
1335 | 1362 | ||
1336 | ret = -ENAMETOOLONG; | 1363 | ret = -ENAMETOOLONG; |
@@ -1393,7 +1420,7 @@ static int afs_link(struct dentry *from, struct inode *dir, | |||
1393 | dvnode = AFS_FS_I(dir); | 1420 | dvnode = AFS_FS_I(dir); |
1394 | data_version = dvnode->status.data_version; | 1421 | data_version = dvnode->status.data_version; |
1395 | 1422 | ||
1396 | _enter("{%x:%u},{%x:%u},{%pd}", | 1423 | _enter("{%llx:%llu},{%llx:%llu},{%pd}", |
1397 | vnode->fid.vid, vnode->fid.vnode, | 1424 | vnode->fid.vid, vnode->fid.vnode, |
1398 | dvnode->fid.vid, dvnode->fid.vnode, | 1425 | dvnode->fid.vid, dvnode->fid.vnode, |
1399 | dentry); | 1426 | dentry); |
@@ -1464,7 +1491,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry, | |||
1464 | u64 data_version = dvnode->status.data_version; | 1491 | u64 data_version = dvnode->status.data_version; |
1465 | int ret; | 1492 | int ret; |
1466 | 1493 | ||
1467 | _enter("{%x:%u},{%pd},%s", | 1494 | _enter("{%llx:%llu},{%pd},%s", |
1468 | dvnode->fid.vid, dvnode->fid.vnode, dentry, | 1495 | dvnode->fid.vid, dvnode->fid.vnode, dentry, |
1469 | content); | 1496 | content); |
1470 | 1497 | ||
@@ -1540,7 +1567,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1540 | orig_data_version = orig_dvnode->status.data_version; | 1567 | orig_data_version = orig_dvnode->status.data_version; |
1541 | new_data_version = new_dvnode->status.data_version; | 1568 | new_data_version = new_dvnode->status.data_version; |
1542 | 1569 | ||
1543 | _enter("{%x:%u},{%x:%u},{%x:%u},{%pd}", | 1570 | _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}", |
1544 | orig_dvnode->fid.vid, orig_dvnode->fid.vnode, | 1571 | orig_dvnode->fid.vid, orig_dvnode->fid.vnode, |
1545 | vnode->fid.vid, vnode->fid.vnode, | 1572 | vnode->fid.vid, vnode->fid.vnode, |
1546 | new_dvnode->fid.vid, new_dvnode->fid.vnode, | 1573 | new_dvnode->fid.vid, new_dvnode->fid.vnode, |
@@ -1607,7 +1634,7 @@ static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags) | |||
1607 | { | 1634 | { |
1608 | struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host); | 1635 | struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host); |
1609 | 1636 | ||
1610 | _enter("{{%x:%u}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index); | 1637 | _enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index); |
1611 | 1638 | ||
1612 | set_page_private(page, 0); | 1639 | set_page_private(page, 0); |
1613 | ClearPagePrivate(page); | 1640 | ClearPagePrivate(page); |
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c index f29c6dade7f6..a9ba81ddf154 100644 --- a/fs/afs/dynroot.c +++ b/fs/afs/dynroot.c | |||
@@ -46,7 +46,7 @@ static int afs_probe_cell_name(struct dentry *dentry) | |||
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | ret = dns_query("afsdb", name, len, "", NULL, NULL); | 49 | ret = dns_query("afsdb", name, len, "srv=1", NULL, NULL); |
50 | if (ret == -ENODATA) | 50 | if (ret == -ENODATA) |
51 | ret = -EDESTADDRREQ; | 51 | ret = -EDESTADDRREQ; |
52 | return ret; | 52 | return ret; |
@@ -62,7 +62,7 @@ struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir) | |||
62 | struct inode *inode; | 62 | struct inode *inode; |
63 | int ret = -ENOENT; | 63 | int ret = -ENOENT; |
64 | 64 | ||
65 | _enter("%p{%pd}, {%x:%u}", | 65 | _enter("%p{%pd}, {%llx:%llu}", |
66 | dentry, dentry, vnode->fid.vid, vnode->fid.vnode); | 66 | dentry, dentry, vnode->fid.vid, vnode->fid.vnode); |
67 | 67 | ||
68 | if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) | 68 | if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) |
diff --git a/fs/afs/file.c b/fs/afs/file.c index 7d4f26198573..d6bc3f5d784b 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
@@ -121,7 +121,7 @@ int afs_open(struct inode *inode, struct file *file) | |||
121 | struct key *key; | 121 | struct key *key; |
122 | int ret; | 122 | int ret; |
123 | 123 | ||
124 | _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); | 124 | _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode); |
125 | 125 | ||
126 | key = afs_request_key(vnode->volume->cell); | 126 | key = afs_request_key(vnode->volume->cell); |
127 | if (IS_ERR(key)) { | 127 | if (IS_ERR(key)) { |
@@ -170,7 +170,7 @@ int afs_release(struct inode *inode, struct file *file) | |||
170 | struct afs_vnode *vnode = AFS_FS_I(inode); | 170 | struct afs_vnode *vnode = AFS_FS_I(inode); |
171 | struct afs_file *af = file->private_data; | 171 | struct afs_file *af = file->private_data; |
172 | 172 | ||
173 | _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); | 173 | _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode); |
174 | 174 | ||
175 | if ((file->f_mode & FMODE_WRITE)) | 175 | if ((file->f_mode & FMODE_WRITE)) |
176 | return vfs_fsync(file, 0); | 176 | return vfs_fsync(file, 0); |
@@ -228,7 +228,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de | |||
228 | struct afs_fs_cursor fc; | 228 | struct afs_fs_cursor fc; |
229 | int ret; | 229 | int ret; |
230 | 230 | ||
231 | _enter("%s{%x:%u.%u},%x,,,", | 231 | _enter("%s{%llx:%llu.%u},%x,,,", |
232 | vnode->volume->name, | 232 | vnode->volume->name, |
233 | vnode->fid.vid, | 233 | vnode->fid.vid, |
234 | vnode->fid.vnode, | 234 | vnode->fid.vnode, |
@@ -634,7 +634,7 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) | |||
634 | struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); | 634 | struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); |
635 | unsigned long priv; | 635 | unsigned long priv; |
636 | 636 | ||
637 | _enter("{{%x:%u}[%lu],%lx},%x", | 637 | _enter("{{%llx:%llu}[%lu],%lx},%x", |
638 | vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, | 638 | vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, |
639 | gfp_flags); | 639 | gfp_flags); |
640 | 640 | ||
diff --git a/fs/afs/flock.c b/fs/afs/flock.c index dc62d15a964b..0568fd986821 100644 --- a/fs/afs/flock.c +++ b/fs/afs/flock.c | |||
@@ -29,7 +29,7 @@ static const struct file_lock_operations afs_lock_ops = { | |||
29 | */ | 29 | */ |
30 | void afs_lock_may_be_available(struct afs_vnode *vnode) | 30 | void afs_lock_may_be_available(struct afs_vnode *vnode) |
31 | { | 31 | { |
32 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | 32 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); |
33 | 33 | ||
34 | queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0); | 34 | queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0); |
35 | } | 35 | } |
@@ -76,7 +76,7 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key, | |||
76 | struct afs_fs_cursor fc; | 76 | struct afs_fs_cursor fc; |
77 | int ret; | 77 | int ret; |
78 | 78 | ||
79 | _enter("%s{%x:%u.%u},%x,%u", | 79 | _enter("%s{%llx:%llu.%u},%x,%u", |
80 | vnode->volume->name, | 80 | vnode->volume->name, |
81 | vnode->fid.vid, | 81 | vnode->fid.vid, |
82 | vnode->fid.vnode, | 82 | vnode->fid.vnode, |
@@ -107,7 +107,7 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key) | |||
107 | struct afs_fs_cursor fc; | 107 | struct afs_fs_cursor fc; |
108 | int ret; | 108 | int ret; |
109 | 109 | ||
110 | _enter("%s{%x:%u.%u},%x", | 110 | _enter("%s{%llx:%llu.%u},%x", |
111 | vnode->volume->name, | 111 | vnode->volume->name, |
112 | vnode->fid.vid, | 112 | vnode->fid.vid, |
113 | vnode->fid.vnode, | 113 | vnode->fid.vnode, |
@@ -138,7 +138,7 @@ static int afs_release_lock(struct afs_vnode *vnode, struct key *key) | |||
138 | struct afs_fs_cursor fc; | 138 | struct afs_fs_cursor fc; |
139 | int ret; | 139 | int ret; |
140 | 140 | ||
141 | _enter("%s{%x:%u.%u},%x", | 141 | _enter("%s{%llx:%llu.%u},%x", |
142 | vnode->volume->name, | 142 | vnode->volume->name, |
143 | vnode->fid.vid, | 143 | vnode->fid.vid, |
144 | vnode->fid.vnode, | 144 | vnode->fid.vnode, |
@@ -175,7 +175,7 @@ void afs_lock_work(struct work_struct *work) | |||
175 | struct key *key; | 175 | struct key *key; |
176 | int ret; | 176 | int ret; |
177 | 177 | ||
178 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | 178 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); |
179 | 179 | ||
180 | spin_lock(&vnode->lock); | 180 | spin_lock(&vnode->lock); |
181 | 181 | ||
@@ -192,7 +192,7 @@ again: | |||
192 | ret = afs_release_lock(vnode, vnode->lock_key); | 192 | ret = afs_release_lock(vnode, vnode->lock_key); |
193 | if (ret < 0) | 193 | if (ret < 0) |
194 | printk(KERN_WARNING "AFS:" | 194 | printk(KERN_WARNING "AFS:" |
195 | " Failed to release lock on {%x:%x} error %d\n", | 195 | " Failed to release lock on {%llx:%llx} error %d\n", |
196 | vnode->fid.vid, vnode->fid.vnode, ret); | 196 | vnode->fid.vid, vnode->fid.vnode, ret); |
197 | 197 | ||
198 | spin_lock(&vnode->lock); | 198 | spin_lock(&vnode->lock); |
@@ -229,7 +229,7 @@ again: | |||
229 | key_put(key); | 229 | key_put(key); |
230 | 230 | ||
231 | if (ret < 0) | 231 | if (ret < 0) |
232 | pr_warning("AFS: Failed to extend lock on {%x:%x} error %d\n", | 232 | pr_warning("AFS: Failed to extend lock on {%llx:%llx} error %d\n", |
233 | vnode->fid.vid, vnode->fid.vnode, ret); | 233 | vnode->fid.vid, vnode->fid.vnode, ret); |
234 | 234 | ||
235 | spin_lock(&vnode->lock); | 235 | spin_lock(&vnode->lock); |
@@ -430,7 +430,7 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl) | |||
430 | struct key *key = afs_file_key(file); | 430 | struct key *key = afs_file_key(file); |
431 | int ret; | 431 | int ret; |
432 | 432 | ||
433 | _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); | 433 | _enter("{%llx:%llu},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); |
434 | 434 | ||
435 | /* only whole-file locks are supported */ | 435 | /* only whole-file locks are supported */ |
436 | if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX) | 436 | if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX) |
@@ -582,7 +582,7 @@ static int afs_do_unlk(struct file *file, struct file_lock *fl) | |||
582 | struct afs_vnode *vnode = AFS_FS_I(locks_inode(file)); | 582 | struct afs_vnode *vnode = AFS_FS_I(locks_inode(file)); |
583 | int ret; | 583 | int ret; |
584 | 584 | ||
585 | _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); | 585 | _enter("{%llx:%llu},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); |
586 | 586 | ||
587 | /* Flush all pending writes before doing anything with locks. */ | 587 | /* Flush all pending writes before doing anything with locks. */ |
588 | vfs_fsync(file, 0); | 588 | vfs_fsync(file, 0); |
@@ -639,7 +639,7 @@ int afs_lock(struct file *file, int cmd, struct file_lock *fl) | |||
639 | { | 639 | { |
640 | struct afs_vnode *vnode = AFS_FS_I(locks_inode(file)); | 640 | struct afs_vnode *vnode = AFS_FS_I(locks_inode(file)); |
641 | 641 | ||
642 | _enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}", | 642 | _enter("{%llx:%llu},%d,{t=%x,fl=%x,r=%Ld:%Ld}", |
643 | vnode->fid.vid, vnode->fid.vnode, cmd, | 643 | vnode->fid.vid, vnode->fid.vnode, cmd, |
644 | fl->fl_type, fl->fl_flags, | 644 | fl->fl_type, fl->fl_flags, |
645 | (long long) fl->fl_start, (long long) fl->fl_end); | 645 | (long long) fl->fl_start, (long long) fl->fl_end); |
@@ -662,7 +662,7 @@ int afs_flock(struct file *file, int cmd, struct file_lock *fl) | |||
662 | { | 662 | { |
663 | struct afs_vnode *vnode = AFS_FS_I(locks_inode(file)); | 663 | struct afs_vnode *vnode = AFS_FS_I(locks_inode(file)); |
664 | 664 | ||
665 | _enter("{%x:%u},%d,{t=%x,fl=%x}", | 665 | _enter("{%llx:%llu},%d,{t=%x,fl=%x}", |
666 | vnode->fid.vid, vnode->fid.vnode, cmd, | 666 | vnode->fid.vid, vnode->fid.vnode, cmd, |
667 | fl->fl_type, fl->fl_flags); | 667 | fl->fl_type, fl->fl_flags); |
668 | 668 | ||
diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c new file mode 100644 index 000000000000..d049cb459742 --- /dev/null +++ b/fs/afs/fs_probe.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* AFS fileserver probing | ||
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 | #include <linux/sched.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include "afs_fs.h" | ||
15 | #include "internal.h" | ||
16 | #include "protocol_yfs.h" | ||
17 | |||
18 | static bool afs_fs_probe_done(struct afs_server *server) | ||
19 | { | ||
20 | if (!atomic_dec_and_test(&server->probe_outstanding)) | ||
21 | return false; | ||
22 | |||
23 | wake_up_var(&server->probe_outstanding); | ||
24 | clear_bit_unlock(AFS_SERVER_FL_PROBING, &server->flags); | ||
25 | wake_up_bit(&server->flags, AFS_SERVER_FL_PROBING); | ||
26 | return true; | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Process the result of probing a fileserver. This is called after successful | ||
31 | * or failed delivery of an FS.GetCapabilities operation. | ||
32 | */ | ||
33 | void afs_fileserver_probe_result(struct afs_call *call) | ||
34 | { | ||
35 | struct afs_addr_list *alist = call->alist; | ||
36 | struct afs_server *server = call->reply[0]; | ||
37 | unsigned int server_index = (long)call->reply[1]; | ||
38 | unsigned int index = call->addr_ix; | ||
39 | unsigned int rtt = UINT_MAX; | ||
40 | bool have_result = false; | ||
41 | u64 _rtt; | ||
42 | int ret = call->error; | ||
43 | |||
44 | _enter("%pU,%u", &server->uuid, index); | ||
45 | |||
46 | spin_lock(&server->probe_lock); | ||
47 | |||
48 | switch (ret) { | ||
49 | case 0: | ||
50 | server->probe.error = 0; | ||
51 | goto responded; | ||
52 | case -ECONNABORTED: | ||
53 | if (!server->probe.responded) { | ||
54 | server->probe.abort_code = call->abort_code; | ||
55 | server->probe.error = ret; | ||
56 | } | ||
57 | goto responded; | ||
58 | case -ENOMEM: | ||
59 | case -ENONET: | ||
60 | server->probe.local_failure = true; | ||
61 | afs_io_error(call, afs_io_error_fs_probe_fail); | ||
62 | goto out; | ||
63 | case -ECONNRESET: /* Responded, but call expired. */ | ||
64 | case -ENETUNREACH: | ||
65 | case -EHOSTUNREACH: | ||
66 | case -ECONNREFUSED: | ||
67 | case -ETIMEDOUT: | ||
68 | case -ETIME: | ||
69 | default: | ||
70 | clear_bit(index, &alist->responded); | ||
71 | set_bit(index, &alist->failed); | ||
72 | if (!server->probe.responded && | ||
73 | (server->probe.error == 0 || | ||
74 | server->probe.error == -ETIMEDOUT || | ||
75 | server->probe.error == -ETIME)) | ||
76 | server->probe.error = ret; | ||
77 | afs_io_error(call, afs_io_error_fs_probe_fail); | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | responded: | ||
82 | set_bit(index, &alist->responded); | ||
83 | clear_bit(index, &alist->failed); | ||
84 | |||
85 | if (call->service_id == YFS_FS_SERVICE) { | ||
86 | server->probe.is_yfs = true; | ||
87 | set_bit(AFS_SERVER_FL_IS_YFS, &server->flags); | ||
88 | alist->addrs[index].srx_service = call->service_id; | ||
89 | } else { | ||
90 | server->probe.not_yfs = true; | ||
91 | if (!server->probe.is_yfs) { | ||
92 | clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags); | ||
93 | alist->addrs[index].srx_service = call->service_id; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /* Get the RTT and scale it to fit into a 32-bit value that represents | ||
98 | * over a minute of time so that we can access it with one instruction | ||
99 | * on a 32-bit system. | ||
100 | */ | ||
101 | _rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall); | ||
102 | _rtt /= 64; | ||
103 | rtt = (_rtt > UINT_MAX) ? UINT_MAX : _rtt; | ||
104 | if (rtt < server->probe.rtt) { | ||
105 | server->probe.rtt = rtt; | ||
106 | alist->preferred = index; | ||
107 | have_result = true; | ||
108 | } | ||
109 | |||
110 | smp_wmb(); /* Set rtt before responded. */ | ||
111 | server->probe.responded = true; | ||
112 | set_bit(AFS_SERVER_FL_PROBED, &server->flags); | ||
113 | out: | ||
114 | spin_unlock(&server->probe_lock); | ||
115 | |||
116 | _debug("probe [%u][%u] %pISpc rtt=%u ret=%d", | ||
117 | server_index, index, &alist->addrs[index].transport, | ||
118 | (unsigned int)rtt, ret); | ||
119 | |||
120 | have_result |= afs_fs_probe_done(server); | ||
121 | if (have_result) { | ||
122 | server->probe.have_result = true; | ||
123 | wake_up_var(&server->probe.have_result); | ||
124 | wake_up_all(&server->probe_wq); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Probe all of a fileserver's addresses to find out the best route and to | ||
130 | * query its capabilities. | ||
131 | */ | ||
132 | static int afs_do_probe_fileserver(struct afs_net *net, | ||
133 | struct afs_server *server, | ||
134 | struct key *key, | ||
135 | unsigned int server_index) | ||
136 | { | ||
137 | struct afs_addr_cursor ac = { | ||
138 | .index = 0, | ||
139 | }; | ||
140 | int ret; | ||
141 | |||
142 | _enter("%pU", &server->uuid); | ||
143 | |||
144 | read_lock(&server->fs_lock); | ||
145 | ac.alist = rcu_dereference_protected(server->addresses, | ||
146 | lockdep_is_held(&server->fs_lock)); | ||
147 | read_unlock(&server->fs_lock); | ||
148 | |||
149 | atomic_set(&server->probe_outstanding, ac.alist->nr_addrs); | ||
150 | memset(&server->probe, 0, sizeof(server->probe)); | ||
151 | server->probe.rtt = UINT_MAX; | ||
152 | |||
153 | for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) { | ||
154 | ret = afs_fs_get_capabilities(net, server, &ac, key, server_index, | ||
155 | true); | ||
156 | if (ret != -EINPROGRESS) { | ||
157 | afs_fs_probe_done(server); | ||
158 | return ret; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Send off probes to all unprobed servers. | ||
167 | */ | ||
168 | int afs_probe_fileservers(struct afs_net *net, struct key *key, | ||
169 | struct afs_server_list *list) | ||
170 | { | ||
171 | struct afs_server *server; | ||
172 | int i, ret; | ||
173 | |||
174 | for (i = 0; i < list->nr_servers; i++) { | ||
175 | server = list->servers[i].server; | ||
176 | if (test_bit(AFS_SERVER_FL_PROBED, &server->flags)) | ||
177 | continue; | ||
178 | |||
179 | if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags)) { | ||
180 | ret = afs_do_probe_fileserver(net, server, key, i); | ||
181 | if (ret) | ||
182 | return ret; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Wait for the first as-yet untried fileserver to respond. | ||
191 | */ | ||
192 | int afs_wait_for_fs_probes(struct afs_server_list *slist, unsigned long untried) | ||
193 | { | ||
194 | struct wait_queue_entry *waits; | ||
195 | struct afs_server *server; | ||
196 | unsigned int rtt = UINT_MAX; | ||
197 | bool have_responders = false; | ||
198 | int pref = -1, i; | ||
199 | |||
200 | _enter("%u,%lx", slist->nr_servers, untried); | ||
201 | |||
202 | /* Only wait for servers that have a probe outstanding. */ | ||
203 | for (i = 0; i < slist->nr_servers; i++) { | ||
204 | if (test_bit(i, &untried)) { | ||
205 | server = slist->servers[i].server; | ||
206 | if (!test_bit(AFS_SERVER_FL_PROBING, &server->flags)) | ||
207 | __clear_bit(i, &untried); | ||
208 | if (server->probe.responded) | ||
209 | have_responders = true; | ||
210 | } | ||
211 | } | ||
212 | if (have_responders || !untried) | ||
213 | return 0; | ||
214 | |||
215 | waits = kmalloc(array_size(slist->nr_servers, sizeof(*waits)), GFP_KERNEL); | ||
216 | if (!waits) | ||
217 | return -ENOMEM; | ||
218 | |||
219 | for (i = 0; i < slist->nr_servers; i++) { | ||
220 | if (test_bit(i, &untried)) { | ||
221 | server = slist->servers[i].server; | ||
222 | init_waitqueue_entry(&waits[i], current); | ||
223 | add_wait_queue(&server->probe_wq, &waits[i]); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | for (;;) { | ||
228 | bool still_probing = false; | ||
229 | |||
230 | set_current_state(TASK_INTERRUPTIBLE); | ||
231 | for (i = 0; i < slist->nr_servers; i++) { | ||
232 | if (test_bit(i, &untried)) { | ||
233 | server = slist->servers[i].server; | ||
234 | if (server->probe.responded) | ||
235 | goto stop; | ||
236 | if (test_bit(AFS_SERVER_FL_PROBING, &server->flags)) | ||
237 | still_probing = true; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | if (!still_probing || unlikely(signal_pending(current))) | ||
242 | goto stop; | ||
243 | schedule(); | ||
244 | } | ||
245 | |||
246 | stop: | ||
247 | set_current_state(TASK_RUNNING); | ||
248 | |||
249 | for (i = 0; i < slist->nr_servers; i++) { | ||
250 | if (test_bit(i, &untried)) { | ||
251 | server = slist->servers[i].server; | ||
252 | if (server->probe.responded && | ||
253 | server->probe.rtt < rtt) { | ||
254 | pref = i; | ||
255 | rtt = server->probe.rtt; | ||
256 | } | ||
257 | |||
258 | remove_wait_queue(&server->probe_wq, &waits[i]); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | kfree(waits); | ||
263 | |||
264 | if (pref == -1 && signal_pending(current)) | ||
265 | return -ERESTARTSYS; | ||
266 | |||
267 | if (pref >= 0) | ||
268 | slist->preferred = pref; | ||
269 | return 0; | ||
270 | } | ||
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 50929cb91732..ca08c83168f5 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
@@ -17,15 +17,10 @@ | |||
17 | #include "internal.h" | 17 | #include "internal.h" |
18 | #include "afs_fs.h" | 18 | #include "afs_fs.h" |
19 | #include "xdr_fs.h" | 19 | #include "xdr_fs.h" |
20 | #include "protocol_yfs.h" | ||
20 | 21 | ||
21 | static const struct afs_fid afs_zero_fid; | 22 | static const struct afs_fid afs_zero_fid; |
22 | 23 | ||
23 | /* | ||
24 | * We need somewhere to discard into in case the server helpfully returns more | ||
25 | * than we asked for in FS.FetchData{,64}. | ||
26 | */ | ||
27 | static u8 afs_discard_buffer[64]; | ||
28 | |||
29 | static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi) | 24 | static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi) |
30 | { | 25 | { |
31 | call->cbi = afs_get_cb_interest(cbi); | 26 | call->cbi = afs_get_cb_interest(cbi); |
@@ -75,8 +70,7 @@ void afs_update_inode_from_status(struct afs_vnode *vnode, | |||
75 | struct timespec64 t; | 70 | struct timespec64 t; |
76 | umode_t mode; | 71 | umode_t mode; |
77 | 72 | ||
78 | t.tv_sec = status->mtime_client; | 73 | t = status->mtime_client; |
79 | t.tv_nsec = 0; | ||
80 | vnode->vfs_inode.i_ctime = t; | 74 | vnode->vfs_inode.i_ctime = t; |
81 | vnode->vfs_inode.i_mtime = t; | 75 | vnode->vfs_inode.i_mtime = t; |
82 | vnode->vfs_inode.i_atime = t; | 76 | vnode->vfs_inode.i_atime = t; |
@@ -96,7 +90,7 @@ void afs_update_inode_from_status(struct afs_vnode *vnode, | |||
96 | if (!(flags & AFS_VNODE_NOT_YET_SET)) { | 90 | if (!(flags & AFS_VNODE_NOT_YET_SET)) { |
97 | if (expected_version && | 91 | if (expected_version && |
98 | *expected_version != status->data_version) { | 92 | *expected_version != status->data_version) { |
99 | _debug("vnode modified %llx on {%x:%u} [exp %llx]", | 93 | _debug("vnode modified %llx on {%llx:%llu} [exp %llx]", |
100 | (unsigned long long) status->data_version, | 94 | (unsigned long long) status->data_version, |
101 | vnode->fid.vid, vnode->fid.vnode, | 95 | vnode->fid.vid, vnode->fid.vnode, |
102 | (unsigned long long) *expected_version); | 96 | (unsigned long long) *expected_version); |
@@ -170,7 +164,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
170 | if (type != status->type && | 164 | if (type != status->type && |
171 | vnode && | 165 | vnode && |
172 | !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { | 166 | !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { |
173 | pr_warning("Vnode %x:%x:%x changed type %u to %u\n", | 167 | pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n", |
174 | vnode->fid.vid, | 168 | vnode->fid.vid, |
175 | vnode->fid.vnode, | 169 | vnode->fid.vnode, |
176 | vnode->fid.unique, | 170 | vnode->fid.unique, |
@@ -200,8 +194,10 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
200 | EXTRACT_M(mode); | 194 | EXTRACT_M(mode); |
201 | EXTRACT_M(group); | 195 | EXTRACT_M(group); |
202 | 196 | ||
203 | status->mtime_client = ntohl(xdr->mtime_client); | 197 | status->mtime_client.tv_sec = ntohl(xdr->mtime_client); |
204 | status->mtime_server = ntohl(xdr->mtime_server); | 198 | status->mtime_client.tv_nsec = 0; |
199 | status->mtime_server.tv_sec = ntohl(xdr->mtime_server); | ||
200 | status->mtime_server.tv_nsec = 0; | ||
205 | status->lock_count = ntohl(xdr->lock_count); | 201 | status->lock_count = ntohl(xdr->lock_count); |
206 | 202 | ||
207 | size = (u64)ntohl(xdr->size_lo); | 203 | size = (u64)ntohl(xdr->size_lo); |
@@ -233,7 +229,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
233 | 229 | ||
234 | bad: | 230 | bad: |
235 | xdr_dump_bad(*_bp); | 231 | xdr_dump_bad(*_bp); |
236 | return afs_protocol_error(call, -EBADMSG); | 232 | return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); |
237 | } | 233 | } |
238 | 234 | ||
239 | /* | 235 | /* |
@@ -273,7 +269,7 @@ static void xdr_decode_AFSCallBack(struct afs_call *call, | |||
273 | 269 | ||
274 | write_seqlock(&vnode->cb_lock); | 270 | write_seqlock(&vnode->cb_lock); |
275 | 271 | ||
276 | if (call->cb_break == afs_cb_break_sum(vnode, cbi)) { | 272 | if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) { |
277 | vnode->cb_version = ntohl(*bp++); | 273 | vnode->cb_version = ntohl(*bp++); |
278 | cb_expiry = ntohl(*bp++); | 274 | cb_expiry = ntohl(*bp++); |
279 | vnode->cb_type = ntohl(*bp++); | 275 | vnode->cb_type = ntohl(*bp++); |
@@ -293,13 +289,19 @@ static void xdr_decode_AFSCallBack(struct afs_call *call, | |||
293 | *_bp = bp; | 289 | *_bp = bp; |
294 | } | 290 | } |
295 | 291 | ||
296 | static void xdr_decode_AFSCallBack_raw(const __be32 **_bp, | 292 | static ktime_t xdr_decode_expiry(struct afs_call *call, u32 expiry) |
293 | { | ||
294 | return ktime_add_ns(call->reply_time, expiry * NSEC_PER_SEC); | ||
295 | } | ||
296 | |||
297 | static void xdr_decode_AFSCallBack_raw(struct afs_call *call, | ||
298 | const __be32 **_bp, | ||
297 | struct afs_callback *cb) | 299 | struct afs_callback *cb) |
298 | { | 300 | { |
299 | const __be32 *bp = *_bp; | 301 | const __be32 *bp = *_bp; |
300 | 302 | ||
301 | cb->version = ntohl(*bp++); | 303 | cb->version = ntohl(*bp++); |
302 | cb->expiry = ntohl(*bp++); | 304 | cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); |
303 | cb->type = ntohl(*bp++); | 305 | cb->type = ntohl(*bp++); |
304 | *_bp = bp; | 306 | *_bp = bp; |
305 | } | 307 | } |
@@ -311,14 +313,18 @@ static void xdr_decode_AFSVolSync(const __be32 **_bp, | |||
311 | struct afs_volsync *volsync) | 313 | struct afs_volsync *volsync) |
312 | { | 314 | { |
313 | const __be32 *bp = *_bp; | 315 | const __be32 *bp = *_bp; |
316 | u32 creation; | ||
314 | 317 | ||
315 | volsync->creation = ntohl(*bp++); | 318 | creation = ntohl(*bp++); |
316 | bp++; /* spare2 */ | 319 | bp++; /* spare2 */ |
317 | bp++; /* spare3 */ | 320 | bp++; /* spare3 */ |
318 | bp++; /* spare4 */ | 321 | bp++; /* spare4 */ |
319 | bp++; /* spare5 */ | 322 | bp++; /* spare5 */ |
320 | bp++; /* spare6 */ | 323 | bp++; /* spare6 */ |
321 | *_bp = bp; | 324 | *_bp = bp; |
325 | |||
326 | if (volsync) | ||
327 | volsync->creation = creation; | ||
322 | } | 328 | } |
323 | 329 | ||
324 | /* | 330 | /* |
@@ -379,6 +385,8 @@ static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, | |||
379 | vs->blocks_in_use = ntohl(*bp++); | 385 | vs->blocks_in_use = ntohl(*bp++); |
380 | vs->part_blocks_avail = ntohl(*bp++); | 386 | vs->part_blocks_avail = ntohl(*bp++); |
381 | vs->part_max_blocks = ntohl(*bp++); | 387 | vs->part_max_blocks = ntohl(*bp++); |
388 | vs->vol_copy_date = 0; | ||
389 | vs->vol_backup_date = 0; | ||
382 | *_bp = bp; | 390 | *_bp = bp; |
383 | } | 391 | } |
384 | 392 | ||
@@ -395,16 +403,16 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) | |||
395 | if (ret < 0) | 403 | if (ret < 0) |
396 | return ret; | 404 | return ret; |
397 | 405 | ||
398 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | 406 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); |
399 | 407 | ||
400 | /* unmarshall the reply once we've received all of it */ | 408 | /* unmarshall the reply once we've received all of it */ |
401 | bp = call->buffer; | 409 | bp = call->buffer; |
402 | if (afs_decode_status(call, &bp, &vnode->status, vnode, | 410 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, |
403 | &call->expected_version, NULL) < 0) | 411 | &call->expected_version, NULL); |
404 | return afs_protocol_error(call, -EBADMSG); | 412 | if (ret < 0) |
413 | return ret; | ||
405 | xdr_decode_AFSCallBack(call, vnode, &bp); | 414 | xdr_decode_AFSCallBack(call, vnode, &bp); |
406 | if (call->reply[1]) | 415 | xdr_decode_AFSVolSync(&bp, call->reply[1]); |
407 | xdr_decode_AFSVolSync(&bp, call->reply[1]); | ||
408 | 416 | ||
409 | _leave(" = 0 [done]"); | 417 | _leave(" = 0 [done]"); |
410 | return 0; | 418 | return 0; |
@@ -431,7 +439,10 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
431 | struct afs_net *net = afs_v2net(vnode); | 439 | struct afs_net *net = afs_v2net(vnode); |
432 | __be32 *bp; | 440 | __be32 *bp; |
433 | 441 | ||
434 | _enter(",%x,{%x:%u},,", | 442 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
443 | return yfs_fs_fetch_file_status(fc, volsync, new_inode); | ||
444 | |||
445 | _enter(",%x,{%llx:%llu},,", | ||
435 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 446 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
436 | 447 | ||
437 | call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode, | 448 | call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode, |
@@ -445,6 +456,7 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
445 | call->reply[0] = vnode; | 456 | call->reply[0] = vnode; |
446 | call->reply[1] = volsync; | 457 | call->reply[1] = volsync; |
447 | call->expected_version = new_inode ? 1 : vnode->status.data_version; | 458 | call->expected_version = new_inode ? 1 : vnode->status.data_version; |
459 | call->want_reply_time = true; | ||
448 | 460 | ||
449 | /* marshall the parameters */ | 461 | /* marshall the parameters */ |
450 | bp = call->request; | 462 | bp = call->request; |
@@ -468,139 +480,117 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) | |||
468 | struct afs_read *req = call->reply[2]; | 480 | struct afs_read *req = call->reply[2]; |
469 | const __be32 *bp; | 481 | const __be32 *bp; |
470 | unsigned int size; | 482 | unsigned int size; |
471 | void *buffer; | ||
472 | int ret; | 483 | int ret; |
473 | 484 | ||
474 | _enter("{%u,%zu/%u;%llu/%llu}", | 485 | _enter("{%u,%zu/%llu}", |
475 | call->unmarshall, call->offset, call->count, | 486 | call->unmarshall, iov_iter_count(&call->iter), req->actual_len); |
476 | req->remain, req->actual_len); | ||
477 | 487 | ||
478 | switch (call->unmarshall) { | 488 | switch (call->unmarshall) { |
479 | case 0: | 489 | case 0: |
480 | req->actual_len = 0; | 490 | req->actual_len = 0; |
481 | call->offset = 0; | 491 | req->index = 0; |
492 | req->offset = req->pos & (PAGE_SIZE - 1); | ||
482 | call->unmarshall++; | 493 | call->unmarshall++; |
483 | if (call->operation_ID != FSFETCHDATA64) { | 494 | if (call->operation_ID == FSFETCHDATA64) { |
484 | call->unmarshall++; | 495 | afs_extract_to_tmp64(call); |
485 | goto no_msw; | 496 | } else { |
497 | call->tmp_u = htonl(0); | ||
498 | afs_extract_to_tmp(call); | ||
486 | } | 499 | } |
487 | 500 | ||
488 | /* extract the upper part of the returned data length of an | ||
489 | * FSFETCHDATA64 op (which should always be 0 using this | ||
490 | * client) */ | ||
491 | case 1: | ||
492 | _debug("extract data length (MSW)"); | ||
493 | ret = afs_extract_data(call, &call->tmp, 4, true); | ||
494 | if (ret < 0) | ||
495 | return ret; | ||
496 | |||
497 | req->actual_len = ntohl(call->tmp); | ||
498 | req->actual_len <<= 32; | ||
499 | call->offset = 0; | ||
500 | call->unmarshall++; | ||
501 | |||
502 | no_msw: | ||
503 | /* extract the returned data length */ | 501 | /* extract the returned data length */ |
504 | case 2: | 502 | case 1: |
505 | _debug("extract data length"); | 503 | _debug("extract data length"); |
506 | ret = afs_extract_data(call, &call->tmp, 4, true); | 504 | ret = afs_extract_data(call, true); |
507 | if (ret < 0) | 505 | if (ret < 0) |
508 | return ret; | 506 | return ret; |
509 | 507 | ||
510 | req->actual_len |= ntohl(call->tmp); | 508 | req->actual_len = be64_to_cpu(call->tmp64); |
511 | _debug("DATA length: %llu", req->actual_len); | 509 | _debug("DATA length: %llu", req->actual_len); |
512 | 510 | req->remain = min(req->len, req->actual_len); | |
513 | req->remain = req->actual_len; | 511 | if (req->remain == 0) |
514 | call->offset = req->pos & (PAGE_SIZE - 1); | ||
515 | req->index = 0; | ||
516 | if (req->actual_len == 0) | ||
517 | goto no_more_data; | 512 | goto no_more_data; |
513 | |||
518 | call->unmarshall++; | 514 | call->unmarshall++; |
519 | 515 | ||
520 | begin_page: | 516 | begin_page: |
521 | ASSERTCMP(req->index, <, req->nr_pages); | 517 | ASSERTCMP(req->index, <, req->nr_pages); |
522 | if (req->remain > PAGE_SIZE - call->offset) | 518 | if (req->remain > PAGE_SIZE - req->offset) |
523 | size = PAGE_SIZE - call->offset; | 519 | size = PAGE_SIZE - req->offset; |
524 | else | 520 | else |
525 | size = req->remain; | 521 | size = req->remain; |
526 | call->count = call->offset + size; | 522 | call->bvec[0].bv_len = size; |
527 | ASSERTCMP(call->count, <=, PAGE_SIZE); | 523 | call->bvec[0].bv_offset = req->offset; |
528 | req->remain -= size; | 524 | call->bvec[0].bv_page = req->pages[req->index]; |
525 | iov_iter_bvec(&call->iter, READ, call->bvec, 1, size); | ||
526 | ASSERTCMP(size, <=, PAGE_SIZE); | ||
529 | 527 | ||
530 | /* extract the returned data */ | 528 | /* extract the returned data */ |
531 | case 3: | 529 | case 2: |
532 | _debug("extract data %llu/%llu %zu/%u", | 530 | _debug("extract data %zu/%llu", |
533 | req->remain, req->actual_len, call->offset, call->count); | 531 | iov_iter_count(&call->iter), req->remain); |
534 | 532 | ||
535 | buffer = kmap(req->pages[req->index]); | 533 | ret = afs_extract_data(call, true); |
536 | ret = afs_extract_data(call, buffer, call->count, true); | ||
537 | kunmap(req->pages[req->index]); | ||
538 | if (ret < 0) | 534 | if (ret < 0) |
539 | return ret; | 535 | return ret; |
540 | if (call->offset == PAGE_SIZE) { | 536 | req->remain -= call->bvec[0].bv_len; |
537 | req->offset += call->bvec[0].bv_len; | ||
538 | ASSERTCMP(req->offset, <=, PAGE_SIZE); | ||
539 | if (req->offset == PAGE_SIZE) { | ||
540 | req->offset = 0; | ||
541 | if (req->page_done) | 541 | if (req->page_done) |
542 | req->page_done(call, req); | 542 | req->page_done(call, req); |
543 | req->index++; | 543 | req->index++; |
544 | if (req->remain > 0) { | 544 | if (req->remain > 0) |
545 | call->offset = 0; | ||
546 | if (req->index >= req->nr_pages) { | ||
547 | call->unmarshall = 4; | ||
548 | goto begin_discard; | ||
549 | } | ||
550 | goto begin_page; | 545 | goto begin_page; |
551 | } | ||
552 | } | 546 | } |
553 | goto no_more_data; | 547 | |
548 | ASSERTCMP(req->remain, ==, 0); | ||
549 | if (req->actual_len <= req->len) | ||
550 | goto no_more_data; | ||
554 | 551 | ||
555 | /* Discard any excess data the server gave us */ | 552 | /* Discard any excess data the server gave us */ |
556 | begin_discard: | 553 | iov_iter_discard(&call->iter, READ, req->actual_len - req->len); |
557 | case 4: | 554 | call->unmarshall = 3; |
558 | size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain); | 555 | case 3: |
559 | call->count = size; | 556 | _debug("extract discard %zu/%llu", |
560 | _debug("extract discard %llu/%llu %zu/%u", | 557 | iov_iter_count(&call->iter), req->actual_len - req->len); |
561 | req->remain, req->actual_len, call->offset, call->count); | 558 | |
562 | 559 | ret = afs_extract_data(call, true); | |
563 | call->offset = 0; | ||
564 | ret = afs_extract_data(call, afs_discard_buffer, call->count, true); | ||
565 | req->remain -= call->offset; | ||
566 | if (ret < 0) | 560 | if (ret < 0) |
567 | return ret; | 561 | return ret; |
568 | if (req->remain > 0) | ||
569 | goto begin_discard; | ||
570 | 562 | ||
571 | no_more_data: | 563 | no_more_data: |
572 | call->offset = 0; | 564 | call->unmarshall = 4; |
573 | call->unmarshall = 5; | 565 | afs_extract_to_buf(call, (21 + 3 + 6) * 4); |
574 | 566 | ||
575 | /* extract the metadata */ | 567 | /* extract the metadata */ |
576 | case 5: | 568 | case 4: |
577 | ret = afs_extract_data(call, call->buffer, | 569 | ret = afs_extract_data(call, false); |
578 | (21 + 3 + 6) * 4, false); | ||
579 | if (ret < 0) | 570 | if (ret < 0) |
580 | return ret; | 571 | return ret; |
581 | 572 | ||
582 | bp = call->buffer; | 573 | bp = call->buffer; |
583 | if (afs_decode_status(call, &bp, &vnode->status, vnode, | 574 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, |
584 | &vnode->status.data_version, req) < 0) | 575 | &vnode->status.data_version, req); |
585 | return afs_protocol_error(call, -EBADMSG); | 576 | if (ret < 0) |
577 | return ret; | ||
586 | xdr_decode_AFSCallBack(call, vnode, &bp); | 578 | xdr_decode_AFSCallBack(call, vnode, &bp); |
587 | if (call->reply[1]) | 579 | xdr_decode_AFSVolSync(&bp, call->reply[1]); |
588 | xdr_decode_AFSVolSync(&bp, call->reply[1]); | ||
589 | 580 | ||
590 | call->offset = 0; | ||
591 | call->unmarshall++; | 581 | call->unmarshall++; |
592 | 582 | ||
593 | case 6: | 583 | case 5: |
594 | break; | 584 | break; |
595 | } | 585 | } |
596 | 586 | ||
597 | for (; req->index < req->nr_pages; req->index++) { | 587 | for (; req->index < req->nr_pages; req->index++) { |
598 | if (call->count < PAGE_SIZE) | 588 | if (req->offset < PAGE_SIZE) |
599 | zero_user_segment(req->pages[req->index], | 589 | zero_user_segment(req->pages[req->index], |
600 | call->count, PAGE_SIZE); | 590 | req->offset, PAGE_SIZE); |
601 | if (req->page_done) | 591 | if (req->page_done) |
602 | req->page_done(call, req); | 592 | req->page_done(call, req); |
603 | call->count = 0; | 593 | req->offset = 0; |
604 | } | 594 | } |
605 | 595 | ||
606 | _leave(" = 0 [done]"); | 596 | _leave(" = 0 [done]"); |
@@ -653,6 +643,7 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req) | |||
653 | call->reply[1] = NULL; /* volsync */ | 643 | call->reply[1] = NULL; /* volsync */ |
654 | call->reply[2] = req; | 644 | call->reply[2] = req; |
655 | call->expected_version = vnode->status.data_version; | 645 | call->expected_version = vnode->status.data_version; |
646 | call->want_reply_time = true; | ||
656 | 647 | ||
657 | /* marshall the parameters */ | 648 | /* marshall the parameters */ |
658 | bp = call->request; | 649 | bp = call->request; |
@@ -682,6 +673,9 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
682 | struct afs_net *net = afs_v2net(vnode); | 673 | struct afs_net *net = afs_v2net(vnode); |
683 | __be32 *bp; | 674 | __be32 *bp; |
684 | 675 | ||
676 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
677 | return yfs_fs_fetch_data(fc, req); | ||
678 | |||
685 | if (upper_32_bits(req->pos) || | 679 | if (upper_32_bits(req->pos) || |
686 | upper_32_bits(req->len) || | 680 | upper_32_bits(req->len) || |
687 | upper_32_bits(req->pos + req->len)) | 681 | upper_32_bits(req->pos + req->len)) |
@@ -698,6 +692,7 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
698 | call->reply[1] = NULL; /* volsync */ | 692 | call->reply[1] = NULL; /* volsync */ |
699 | call->reply[2] = req; | 693 | call->reply[2] = req; |
700 | call->expected_version = vnode->status.data_version; | 694 | call->expected_version = vnode->status.data_version; |
695 | call->want_reply_time = true; | ||
701 | 696 | ||
702 | /* marshall the parameters */ | 697 | /* marshall the parameters */ |
703 | bp = call->request; | 698 | bp = call->request; |
@@ -733,11 +728,14 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call) | |||
733 | /* unmarshall the reply once we've received all of it */ | 728 | /* unmarshall the reply once we've received all of it */ |
734 | bp = call->buffer; | 729 | bp = call->buffer; |
735 | xdr_decode_AFSFid(&bp, call->reply[1]); | 730 | xdr_decode_AFSFid(&bp, call->reply[1]); |
736 | if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 || | 731 | ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); |
737 | afs_decode_status(call, &bp, &vnode->status, vnode, | 732 | if (ret < 0) |
738 | &call->expected_version, NULL) < 0) | 733 | return ret; |
739 | return afs_protocol_error(call, -EBADMSG); | 734 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, |
740 | xdr_decode_AFSCallBack_raw(&bp, call->reply[3]); | 735 | &call->expected_version, NULL); |
736 | if (ret < 0) | ||
737 | return ret; | ||
738 | xdr_decode_AFSCallBack_raw(call, &bp, call->reply[3]); | ||
741 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 739 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
742 | 740 | ||
743 | _leave(" = 0 [done]"); | 741 | _leave(" = 0 [done]"); |
@@ -778,6 +776,15 @@ int afs_fs_create(struct afs_fs_cursor *fc, | |||
778 | size_t namesz, reqsz, padsz; | 776 | size_t namesz, reqsz, padsz; |
779 | __be32 *bp; | 777 | __be32 *bp; |
780 | 778 | ||
779 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){ | ||
780 | if (S_ISDIR(mode)) | ||
781 | return yfs_fs_make_dir(fc, name, mode, current_data_version, | ||
782 | newfid, newstatus, newcb); | ||
783 | else | ||
784 | return yfs_fs_create_file(fc, name, mode, current_data_version, | ||
785 | newfid, newstatus, newcb); | ||
786 | } | ||
787 | |||
781 | _enter(""); | 788 | _enter(""); |
782 | 789 | ||
783 | namesz = strlen(name); | 790 | namesz = strlen(name); |
@@ -796,6 +803,7 @@ int afs_fs_create(struct afs_fs_cursor *fc, | |||
796 | call->reply[2] = newstatus; | 803 | call->reply[2] = newstatus; |
797 | call->reply[3] = newcb; | 804 | call->reply[3] = newcb; |
798 | call->expected_version = current_data_version + 1; | 805 | call->expected_version = current_data_version + 1; |
806 | call->want_reply_time = true; | ||
799 | 807 | ||
800 | /* marshall the parameters */ | 808 | /* marshall the parameters */ |
801 | bp = call->request; | 809 | bp = call->request; |
@@ -839,9 +847,10 @@ static int afs_deliver_fs_remove(struct afs_call *call) | |||
839 | 847 | ||
840 | /* unmarshall the reply once we've received all of it */ | 848 | /* unmarshall the reply once we've received all of it */ |
841 | bp = call->buffer; | 849 | bp = call->buffer; |
842 | if (afs_decode_status(call, &bp, &vnode->status, vnode, | 850 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, |
843 | &call->expected_version, NULL) < 0) | 851 | &call->expected_version, NULL); |
844 | return afs_protocol_error(call, -EBADMSG); | 852 | if (ret < 0) |
853 | return ret; | ||
845 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 854 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
846 | 855 | ||
847 | _leave(" = 0 [done]"); | 856 | _leave(" = 0 [done]"); |
@@ -868,15 +877,18 @@ static const struct afs_call_type afs_RXFSRemoveDir = { | |||
868 | /* | 877 | /* |
869 | * remove a file or directory | 878 | * remove a file or directory |
870 | */ | 879 | */ |
871 | int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir, | 880 | int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, |
872 | u64 current_data_version) | 881 | const char *name, bool isdir, u64 current_data_version) |
873 | { | 882 | { |
874 | struct afs_vnode *vnode = fc->vnode; | 883 | struct afs_vnode *dvnode = fc->vnode; |
875 | struct afs_call *call; | 884 | struct afs_call *call; |
876 | struct afs_net *net = afs_v2net(vnode); | 885 | struct afs_net *net = afs_v2net(dvnode); |
877 | size_t namesz, reqsz, padsz; | 886 | size_t namesz, reqsz, padsz; |
878 | __be32 *bp; | 887 | __be32 *bp; |
879 | 888 | ||
889 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
890 | return yfs_fs_remove(fc, vnode, name, isdir, current_data_version); | ||
891 | |||
880 | _enter(""); | 892 | _enter(""); |
881 | 893 | ||
882 | namesz = strlen(name); | 894 | namesz = strlen(name); |
@@ -890,15 +902,16 @@ int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir, | |||
890 | return -ENOMEM; | 902 | return -ENOMEM; |
891 | 903 | ||
892 | call->key = fc->key; | 904 | call->key = fc->key; |
893 | call->reply[0] = vnode; | 905 | call->reply[0] = dvnode; |
906 | call->reply[1] = vnode; | ||
894 | call->expected_version = current_data_version + 1; | 907 | call->expected_version = current_data_version + 1; |
895 | 908 | ||
896 | /* marshall the parameters */ | 909 | /* marshall the parameters */ |
897 | bp = call->request; | 910 | bp = call->request; |
898 | *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); | 911 | *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); |
899 | *bp++ = htonl(vnode->fid.vid); | 912 | *bp++ = htonl(dvnode->fid.vid); |
900 | *bp++ = htonl(vnode->fid.vnode); | 913 | *bp++ = htonl(dvnode->fid.vnode); |
901 | *bp++ = htonl(vnode->fid.unique); | 914 | *bp++ = htonl(dvnode->fid.unique); |
902 | *bp++ = htonl(namesz); | 915 | *bp++ = htonl(namesz); |
903 | memcpy(bp, name, namesz); | 916 | memcpy(bp, name, namesz); |
904 | bp = (void *) bp + namesz; | 917 | bp = (void *) bp + namesz; |
@@ -908,7 +921,7 @@ int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir, | |||
908 | } | 921 | } |
909 | 922 | ||
910 | afs_use_fs_server(call, fc->cbi); | 923 | afs_use_fs_server(call, fc->cbi); |
911 | trace_afs_make_fs_call(call, &vnode->fid); | 924 | trace_afs_make_fs_call(call, &dvnode->fid); |
912 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | 925 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); |
913 | } | 926 | } |
914 | 927 | ||
@@ -929,10 +942,13 @@ static int afs_deliver_fs_link(struct afs_call *call) | |||
929 | 942 | ||
930 | /* unmarshall the reply once we've received all of it */ | 943 | /* unmarshall the reply once we've received all of it */ |
931 | bp = call->buffer; | 944 | bp = call->buffer; |
932 | if (afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 || | 945 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL); |
933 | afs_decode_status(call, &bp, &dvnode->status, dvnode, | 946 | if (ret < 0) |
934 | &call->expected_version, NULL) < 0) | 947 | return ret; |
935 | return afs_protocol_error(call, -EBADMSG); | 948 | ret = afs_decode_status(call, &bp, &dvnode->status, dvnode, |
949 | &call->expected_version, NULL); | ||
950 | if (ret < 0) | ||
951 | return ret; | ||
936 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 952 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
937 | 953 | ||
938 | _leave(" = 0 [done]"); | 954 | _leave(" = 0 [done]"); |
@@ -961,6 +977,9 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
961 | size_t namesz, reqsz, padsz; | 977 | size_t namesz, reqsz, padsz; |
962 | __be32 *bp; | 978 | __be32 *bp; |
963 | 979 | ||
980 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
981 | return yfs_fs_link(fc, vnode, name, current_data_version); | ||
982 | |||
964 | _enter(""); | 983 | _enter(""); |
965 | 984 | ||
966 | namesz = strlen(name); | 985 | namesz = strlen(name); |
@@ -1016,10 +1035,13 @@ static int afs_deliver_fs_symlink(struct afs_call *call) | |||
1016 | /* unmarshall the reply once we've received all of it */ | 1035 | /* unmarshall the reply once we've received all of it */ |
1017 | bp = call->buffer; | 1036 | bp = call->buffer; |
1018 | xdr_decode_AFSFid(&bp, call->reply[1]); | 1037 | xdr_decode_AFSFid(&bp, call->reply[1]); |
1019 | if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) || | 1038 | ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); |
1020 | afs_decode_status(call, &bp, &vnode->status, vnode, | 1039 | if (ret < 0) |
1021 | &call->expected_version, NULL) < 0) | 1040 | return ret; |
1022 | return afs_protocol_error(call, -EBADMSG); | 1041 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, |
1042 | &call->expected_version, NULL); | ||
1043 | if (ret < 0) | ||
1044 | return ret; | ||
1023 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1045 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
1024 | 1046 | ||
1025 | _leave(" = 0 [done]"); | 1047 | _leave(" = 0 [done]"); |
@@ -1052,6 +1074,10 @@ int afs_fs_symlink(struct afs_fs_cursor *fc, | |||
1052 | size_t namesz, reqsz, padsz, c_namesz, c_padsz; | 1074 | size_t namesz, reqsz, padsz, c_namesz, c_padsz; |
1053 | __be32 *bp; | 1075 | __be32 *bp; |
1054 | 1076 | ||
1077 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
1078 | return yfs_fs_symlink(fc, name, contents, current_data_version, | ||
1079 | newfid, newstatus); | ||
1080 | |||
1055 | _enter(""); | 1081 | _enter(""); |
1056 | 1082 | ||
1057 | namesz = strlen(name); | 1083 | namesz = strlen(name); |
@@ -1122,13 +1148,16 @@ static int afs_deliver_fs_rename(struct afs_call *call) | |||
1122 | 1148 | ||
1123 | /* unmarshall the reply once we've received all of it */ | 1149 | /* unmarshall the reply once we've received all of it */ |
1124 | bp = call->buffer; | 1150 | bp = call->buffer; |
1125 | if (afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode, | 1151 | ret = afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode, |
1126 | &call->expected_version, NULL) < 0) | 1152 | &call->expected_version, NULL); |
1127 | return afs_protocol_error(call, -EBADMSG); | 1153 | if (ret < 0) |
1128 | if (new_dvnode != orig_dvnode && | 1154 | return ret; |
1129 | afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode, | 1155 | if (new_dvnode != orig_dvnode) { |
1130 | &call->expected_version_2, NULL) < 0) | 1156 | ret = afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode, |
1131 | return afs_protocol_error(call, -EBADMSG); | 1157 | &call->expected_version_2, NULL); |
1158 | if (ret < 0) | ||
1159 | return ret; | ||
1160 | } | ||
1132 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1161 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
1133 | 1162 | ||
1134 | _leave(" = 0 [done]"); | 1163 | _leave(" = 0 [done]"); |
@@ -1161,6 +1190,12 @@ int afs_fs_rename(struct afs_fs_cursor *fc, | |||
1161 | size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; | 1190 | size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; |
1162 | __be32 *bp; | 1191 | __be32 *bp; |
1163 | 1192 | ||
1193 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
1194 | return yfs_fs_rename(fc, orig_name, | ||
1195 | new_dvnode, new_name, | ||
1196 | current_orig_data_version, | ||
1197 | current_new_data_version); | ||
1198 | |||
1164 | _enter(""); | 1199 | _enter(""); |
1165 | 1200 | ||
1166 | o_namesz = strlen(orig_name); | 1201 | o_namesz = strlen(orig_name); |
@@ -1231,9 +1266,10 @@ static int afs_deliver_fs_store_data(struct afs_call *call) | |||
1231 | 1266 | ||
1232 | /* unmarshall the reply once we've received all of it */ | 1267 | /* unmarshall the reply once we've received all of it */ |
1233 | bp = call->buffer; | 1268 | bp = call->buffer; |
1234 | if (afs_decode_status(call, &bp, &vnode->status, vnode, | 1269 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, |
1235 | &call->expected_version, NULL) < 0) | 1270 | &call->expected_version, NULL); |
1236 | return afs_protocol_error(call, -EBADMSG); | 1271 | if (ret < 0) |
1272 | return ret; | ||
1237 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1273 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
1238 | 1274 | ||
1239 | afs_pages_written_back(vnode, call); | 1275 | afs_pages_written_back(vnode, call); |
@@ -1273,7 +1309,7 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc, | |||
1273 | struct afs_net *net = afs_v2net(vnode); | 1309 | struct afs_net *net = afs_v2net(vnode); |
1274 | __be32 *bp; | 1310 | __be32 *bp; |
1275 | 1311 | ||
1276 | _enter(",%x,{%x:%u},,", | 1312 | _enter(",%x,{%llx:%llu},,", |
1277 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1313 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
1278 | 1314 | ||
1279 | call = afs_alloc_flat_call(net, &afs_RXFSStoreData64, | 1315 | call = afs_alloc_flat_call(net, &afs_RXFSStoreData64, |
@@ -1330,7 +1366,10 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | |||
1330 | loff_t size, pos, i_size; | 1366 | loff_t size, pos, i_size; |
1331 | __be32 *bp; | 1367 | __be32 *bp; |
1332 | 1368 | ||
1333 | _enter(",%x,{%x:%u},,", | 1369 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
1370 | return yfs_fs_store_data(fc, mapping, first, last, offset, to); | ||
1371 | |||
1372 | _enter(",%x,{%llx:%llu},,", | ||
1334 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1373 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
1335 | 1374 | ||
1336 | size = (loff_t)to - (loff_t)offset; | 1375 | size = (loff_t)to - (loff_t)offset; |
@@ -1407,9 +1446,10 @@ static int afs_deliver_fs_store_status(struct afs_call *call) | |||
1407 | 1446 | ||
1408 | /* unmarshall the reply once we've received all of it */ | 1447 | /* unmarshall the reply once we've received all of it */ |
1409 | bp = call->buffer; | 1448 | bp = call->buffer; |
1410 | if (afs_decode_status(call, &bp, &vnode->status, vnode, | 1449 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, |
1411 | &call->expected_version, NULL) < 0) | 1450 | &call->expected_version, NULL); |
1412 | return afs_protocol_error(call, -EBADMSG); | 1451 | if (ret < 0) |
1452 | return ret; | ||
1413 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1453 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
1414 | 1454 | ||
1415 | _leave(" = 0 [done]"); | 1455 | _leave(" = 0 [done]"); |
@@ -1451,7 +1491,7 @@ static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr) | |||
1451 | struct afs_net *net = afs_v2net(vnode); | 1491 | struct afs_net *net = afs_v2net(vnode); |
1452 | __be32 *bp; | 1492 | __be32 *bp; |
1453 | 1493 | ||
1454 | _enter(",%x,{%x:%u},,", | 1494 | _enter(",%x,{%llx:%llu},,", |
1455 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1495 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
1456 | 1496 | ||
1457 | ASSERT(attr->ia_valid & ATTR_SIZE); | 1497 | ASSERT(attr->ia_valid & ATTR_SIZE); |
@@ -1498,7 +1538,7 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | |||
1498 | struct afs_net *net = afs_v2net(vnode); | 1538 | struct afs_net *net = afs_v2net(vnode); |
1499 | __be32 *bp; | 1539 | __be32 *bp; |
1500 | 1540 | ||
1501 | _enter(",%x,{%x:%u},,", | 1541 | _enter(",%x,{%llx:%llu},,", |
1502 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1542 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
1503 | 1543 | ||
1504 | ASSERT(attr->ia_valid & ATTR_SIZE); | 1544 | ASSERT(attr->ia_valid & ATTR_SIZE); |
@@ -1544,10 +1584,13 @@ int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | |||
1544 | struct afs_net *net = afs_v2net(vnode); | 1584 | struct afs_net *net = afs_v2net(vnode); |
1545 | __be32 *bp; | 1585 | __be32 *bp; |
1546 | 1586 | ||
1587 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
1588 | return yfs_fs_setattr(fc, attr); | ||
1589 | |||
1547 | if (attr->ia_valid & ATTR_SIZE) | 1590 | if (attr->ia_valid & ATTR_SIZE) |
1548 | return afs_fs_setattr_size(fc, attr); | 1591 | return afs_fs_setattr_size(fc, attr); |
1549 | 1592 | ||
1550 | _enter(",%x,{%x:%u},,", | 1593 | _enter(",%x,{%llx:%llu},,", |
1551 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1594 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
1552 | 1595 | ||
1553 | call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus, | 1596 | call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus, |
@@ -1581,164 +1624,114 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
1581 | { | 1624 | { |
1582 | const __be32 *bp; | 1625 | const __be32 *bp; |
1583 | char *p; | 1626 | char *p; |
1627 | u32 size; | ||
1584 | int ret; | 1628 | int ret; |
1585 | 1629 | ||
1586 | _enter("{%u}", call->unmarshall); | 1630 | _enter("{%u}", call->unmarshall); |
1587 | 1631 | ||
1588 | switch (call->unmarshall) { | 1632 | switch (call->unmarshall) { |
1589 | case 0: | 1633 | case 0: |
1590 | call->offset = 0; | ||
1591 | call->unmarshall++; | 1634 | call->unmarshall++; |
1635 | afs_extract_to_buf(call, 12 * 4); | ||
1592 | 1636 | ||
1593 | /* extract the returned status record */ | 1637 | /* extract the returned status record */ |
1594 | case 1: | 1638 | case 1: |
1595 | _debug("extract status"); | 1639 | _debug("extract status"); |
1596 | ret = afs_extract_data(call, call->buffer, | 1640 | ret = afs_extract_data(call, true); |
1597 | 12 * 4, true); | ||
1598 | if (ret < 0) | 1641 | if (ret < 0) |
1599 | return ret; | 1642 | return ret; |
1600 | 1643 | ||
1601 | bp = call->buffer; | 1644 | bp = call->buffer; |
1602 | xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]); | 1645 | xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]); |
1603 | call->offset = 0; | ||
1604 | call->unmarshall++; | 1646 | call->unmarshall++; |
1647 | afs_extract_to_tmp(call); | ||
1605 | 1648 | ||
1606 | /* extract the volume name length */ | 1649 | /* extract the volume name length */ |
1607 | case 2: | 1650 | case 2: |
1608 | ret = afs_extract_data(call, &call->tmp, 4, true); | 1651 | ret = afs_extract_data(call, true); |
1609 | if (ret < 0) | 1652 | if (ret < 0) |
1610 | return ret; | 1653 | return ret; |
1611 | 1654 | ||
1612 | call->count = ntohl(call->tmp); | 1655 | call->count = ntohl(call->tmp); |
1613 | _debug("volname length: %u", call->count); | 1656 | _debug("volname length: %u", call->count); |
1614 | if (call->count >= AFSNAMEMAX) | 1657 | if (call->count >= AFSNAMEMAX) |
1615 | return afs_protocol_error(call, -EBADMSG); | 1658 | return afs_protocol_error(call, -EBADMSG, |
1616 | call->offset = 0; | 1659 | afs_eproto_volname_len); |
1660 | size = (call->count + 3) & ~3; /* It's padded */ | ||
1661 | afs_extract_begin(call, call->reply[2], size); | ||
1617 | call->unmarshall++; | 1662 | call->unmarshall++; |
1618 | 1663 | ||
1619 | /* extract the volume name */ | 1664 | /* extract the volume name */ |
1620 | case 3: | 1665 | case 3: |
1621 | _debug("extract volname"); | 1666 | _debug("extract volname"); |
1622 | if (call->count > 0) { | 1667 | ret = afs_extract_data(call, true); |
1623 | ret = afs_extract_data(call, call->reply[2], | 1668 | if (ret < 0) |
1624 | call->count, true); | 1669 | return ret; |
1625 | if (ret < 0) | ||
1626 | return ret; | ||
1627 | } | ||
1628 | 1670 | ||
1629 | p = call->reply[2]; | 1671 | p = call->reply[2]; |
1630 | p[call->count] = 0; | 1672 | p[call->count] = 0; |
1631 | _debug("volname '%s'", p); | 1673 | _debug("volname '%s'", p); |
1632 | 1674 | afs_extract_to_tmp(call); | |
1633 | call->offset = 0; | ||
1634 | call->unmarshall++; | 1675 | call->unmarshall++; |
1635 | 1676 | ||
1636 | /* extract the volume name padding */ | ||
1637 | if ((call->count & 3) == 0) { | ||
1638 | call->unmarshall++; | ||
1639 | goto no_volname_padding; | ||
1640 | } | ||
1641 | call->count = 4 - (call->count & 3); | ||
1642 | |||
1643 | case 4: | ||
1644 | ret = afs_extract_data(call, call->buffer, | ||
1645 | call->count, true); | ||
1646 | if (ret < 0) | ||
1647 | return ret; | ||
1648 | |||
1649 | call->offset = 0; | ||
1650 | call->unmarshall++; | ||
1651 | no_volname_padding: | ||
1652 | |||
1653 | /* extract the offline message length */ | 1677 | /* extract the offline message length */ |
1654 | case 5: | 1678 | case 4: |
1655 | ret = afs_extract_data(call, &call->tmp, 4, true); | 1679 | ret = afs_extract_data(call, true); |
1656 | if (ret < 0) | 1680 | if (ret < 0) |
1657 | return ret; | 1681 | return ret; |
1658 | 1682 | ||
1659 | call->count = ntohl(call->tmp); | 1683 | call->count = ntohl(call->tmp); |
1660 | _debug("offline msg length: %u", call->count); | 1684 | _debug("offline msg length: %u", call->count); |
1661 | if (call->count >= AFSNAMEMAX) | 1685 | if (call->count >= AFSNAMEMAX) |
1662 | return afs_protocol_error(call, -EBADMSG); | 1686 | return afs_protocol_error(call, -EBADMSG, |
1663 | call->offset = 0; | 1687 | afs_eproto_offline_msg_len); |
1688 | size = (call->count + 3) & ~3; /* It's padded */ | ||
1689 | afs_extract_begin(call, call->reply[2], size); | ||
1664 | call->unmarshall++; | 1690 | call->unmarshall++; |
1665 | 1691 | ||
1666 | /* extract the offline message */ | 1692 | /* extract the offline message */ |
1667 | case 6: | 1693 | case 5: |
1668 | _debug("extract offline"); | 1694 | _debug("extract offline"); |
1669 | if (call->count > 0) { | 1695 | ret = afs_extract_data(call, true); |
1670 | ret = afs_extract_data(call, call->reply[2], | 1696 | if (ret < 0) |
1671 | call->count, true); | 1697 | return ret; |
1672 | if (ret < 0) | ||
1673 | return ret; | ||
1674 | } | ||
1675 | 1698 | ||
1676 | p = call->reply[2]; | 1699 | p = call->reply[2]; |
1677 | p[call->count] = 0; | 1700 | p[call->count] = 0; |
1678 | _debug("offline '%s'", p); | 1701 | _debug("offline '%s'", p); |
1679 | 1702 | ||
1680 | call->offset = 0; | 1703 | afs_extract_to_tmp(call); |
1681 | call->unmarshall++; | 1704 | call->unmarshall++; |
1682 | 1705 | ||
1683 | /* extract the offline message padding */ | ||
1684 | if ((call->count & 3) == 0) { | ||
1685 | call->unmarshall++; | ||
1686 | goto no_offline_padding; | ||
1687 | } | ||
1688 | call->count = 4 - (call->count & 3); | ||
1689 | |||
1690 | case 7: | ||
1691 | ret = afs_extract_data(call, call->buffer, | ||
1692 | call->count, true); | ||
1693 | if (ret < 0) | ||
1694 | return ret; | ||
1695 | |||
1696 | call->offset = 0; | ||
1697 | call->unmarshall++; | ||
1698 | no_offline_padding: | ||
1699 | |||
1700 | /* extract the message of the day length */ | 1706 | /* extract the message of the day length */ |
1701 | case 8: | 1707 | case 6: |
1702 | ret = afs_extract_data(call, &call->tmp, 4, true); | 1708 | ret = afs_extract_data(call, true); |
1703 | if (ret < 0) | 1709 | if (ret < 0) |
1704 | return ret; | 1710 | return ret; |
1705 | 1711 | ||
1706 | call->count = ntohl(call->tmp); | 1712 | call->count = ntohl(call->tmp); |
1707 | _debug("motd length: %u", call->count); | 1713 | _debug("motd length: %u", call->count); |
1708 | if (call->count >= AFSNAMEMAX) | 1714 | if (call->count >= AFSNAMEMAX) |
1709 | return afs_protocol_error(call, -EBADMSG); | 1715 | return afs_protocol_error(call, -EBADMSG, |
1710 | call->offset = 0; | 1716 | afs_eproto_motd_len); |
1717 | size = (call->count + 3) & ~3; /* It's padded */ | ||
1718 | afs_extract_begin(call, call->reply[2], size); | ||
1711 | call->unmarshall++; | 1719 | call->unmarshall++; |
1712 | 1720 | ||
1713 | /* extract the message of the day */ | 1721 | /* extract the message of the day */ |
1714 | case 9: | 1722 | case 7: |
1715 | _debug("extract motd"); | 1723 | _debug("extract motd"); |
1716 | if (call->count > 0) { | 1724 | ret = afs_extract_data(call, false); |
1717 | ret = afs_extract_data(call, call->reply[2], | 1725 | if (ret < 0) |
1718 | call->count, true); | 1726 | return ret; |
1719 | if (ret < 0) | ||
1720 | return ret; | ||
1721 | } | ||
1722 | 1727 | ||
1723 | p = call->reply[2]; | 1728 | p = call->reply[2]; |
1724 | p[call->count] = 0; | 1729 | p[call->count] = 0; |
1725 | _debug("motd '%s'", p); | 1730 | _debug("motd '%s'", p); |
1726 | 1731 | ||
1727 | call->offset = 0; | ||
1728 | call->unmarshall++; | 1732 | call->unmarshall++; |
1729 | 1733 | ||
1730 | /* extract the message of the day padding */ | 1734 | case 8: |
1731 | call->count = (4 - (call->count & 3)) & 3; | ||
1732 | |||
1733 | case 10: | ||
1734 | ret = afs_extract_data(call, call->buffer, | ||
1735 | call->count, false); | ||
1736 | if (ret < 0) | ||
1737 | return ret; | ||
1738 | |||
1739 | call->offset = 0; | ||
1740 | call->unmarshall++; | ||
1741 | case 11: | ||
1742 | break; | 1735 | break; |
1743 | } | 1736 | } |
1744 | 1737 | ||
@@ -1778,6 +1771,9 @@ int afs_fs_get_volume_status(struct afs_fs_cursor *fc, | |||
1778 | __be32 *bp; | 1771 | __be32 *bp; |
1779 | void *tmpbuf; | 1772 | void *tmpbuf; |
1780 | 1773 | ||
1774 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
1775 | return yfs_fs_get_volume_status(fc, vs); | ||
1776 | |||
1781 | _enter(""); | 1777 | _enter(""); |
1782 | 1778 | ||
1783 | tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL); | 1779 | tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL); |
@@ -1867,6 +1863,9 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | |||
1867 | struct afs_net *net = afs_v2net(vnode); | 1863 | struct afs_net *net = afs_v2net(vnode); |
1868 | __be32 *bp; | 1864 | __be32 *bp; |
1869 | 1865 | ||
1866 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
1867 | return yfs_fs_set_lock(fc, type); | ||
1868 | |||
1870 | _enter(""); | 1869 | _enter(""); |
1871 | 1870 | ||
1872 | call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4); | 1871 | call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4); |
@@ -1899,6 +1898,9 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc) | |||
1899 | struct afs_net *net = afs_v2net(vnode); | 1898 | struct afs_net *net = afs_v2net(vnode); |
1900 | __be32 *bp; | 1899 | __be32 *bp; |
1901 | 1900 | ||
1901 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
1902 | return yfs_fs_extend_lock(fc); | ||
1903 | |||
1902 | _enter(""); | 1904 | _enter(""); |
1903 | 1905 | ||
1904 | call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4); | 1906 | call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4); |
@@ -1930,6 +1932,9 @@ int afs_fs_release_lock(struct afs_fs_cursor *fc) | |||
1930 | struct afs_net *net = afs_v2net(vnode); | 1932 | struct afs_net *net = afs_v2net(vnode); |
1931 | __be32 *bp; | 1933 | __be32 *bp; |
1932 | 1934 | ||
1935 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | ||
1936 | return yfs_fs_release_lock(fc); | ||
1937 | |||
1933 | _enter(""); | 1938 | _enter(""); |
1934 | 1939 | ||
1935 | call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4); | 1940 | call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4); |
@@ -2004,19 +2009,16 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call) | |||
2004 | u32 count; | 2009 | u32 count; |
2005 | int ret; | 2010 | int ret; |
2006 | 2011 | ||
2007 | _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); | 2012 | _enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter)); |
2008 | 2013 | ||
2009 | again: | ||
2010 | switch (call->unmarshall) { | 2014 | switch (call->unmarshall) { |
2011 | case 0: | 2015 | case 0: |
2012 | call->offset = 0; | 2016 | afs_extract_to_tmp(call); |
2013 | call->unmarshall++; | 2017 | call->unmarshall++; |
2014 | 2018 | ||
2015 | /* Extract the capabilities word count */ | 2019 | /* Extract the capabilities word count */ |
2016 | case 1: | 2020 | case 1: |
2017 | ret = afs_extract_data(call, &call->tmp, | 2021 | ret = afs_extract_data(call, true); |
2018 | 1 * sizeof(__be32), | ||
2019 | true); | ||
2020 | if (ret < 0) | 2022 | if (ret < 0) |
2021 | return ret; | 2023 | return ret; |
2022 | 2024 | ||
@@ -2024,24 +2026,17 @@ again: | |||
2024 | 2026 | ||
2025 | call->count = count; | 2027 | call->count = count; |
2026 | call->count2 = count; | 2028 | call->count2 = count; |
2027 | call->offset = 0; | 2029 | iov_iter_discard(&call->iter, READ, count * sizeof(__be32)); |
2028 | call->unmarshall++; | 2030 | call->unmarshall++; |
2029 | 2031 | ||
2030 | /* Extract capabilities words */ | 2032 | /* Extract capabilities words */ |
2031 | case 2: | 2033 | case 2: |
2032 | count = min(call->count, 16U); | 2034 | ret = afs_extract_data(call, false); |
2033 | ret = afs_extract_data(call, call->buffer, | ||
2034 | count * sizeof(__be32), | ||
2035 | call->count > 16); | ||
2036 | if (ret < 0) | 2035 | if (ret < 0) |
2037 | return ret; | 2036 | return ret; |
2038 | 2037 | ||
2039 | /* TODO: Examine capabilities */ | 2038 | /* TODO: Examine capabilities */ |
2040 | 2039 | ||
2041 | call->count -= count; | ||
2042 | if (call->count > 0) | ||
2043 | goto again; | ||
2044 | call->offset = 0; | ||
2045 | call->unmarshall++; | 2040 | call->unmarshall++; |
2046 | break; | 2041 | break; |
2047 | } | 2042 | } |
@@ -2050,6 +2045,14 @@ again: | |||
2050 | return 0; | 2045 | return 0; |
2051 | } | 2046 | } |
2052 | 2047 | ||
2048 | static void afs_destroy_fs_get_capabilities(struct afs_call *call) | ||
2049 | { | ||
2050 | struct afs_server *server = call->reply[0]; | ||
2051 | |||
2052 | afs_put_server(call->net, server); | ||
2053 | afs_flat_call_destructor(call); | ||
2054 | } | ||
2055 | |||
2053 | /* | 2056 | /* |
2054 | * FS.GetCapabilities operation type | 2057 | * FS.GetCapabilities operation type |
2055 | */ | 2058 | */ |
@@ -2057,7 +2060,8 @@ static const struct afs_call_type afs_RXFSGetCapabilities = { | |||
2057 | .name = "FS.GetCapabilities", | 2060 | .name = "FS.GetCapabilities", |
2058 | .op = afs_FS_GetCapabilities, | 2061 | .op = afs_FS_GetCapabilities, |
2059 | .deliver = afs_deliver_fs_get_capabilities, | 2062 | .deliver = afs_deliver_fs_get_capabilities, |
2060 | .destructor = afs_flat_call_destructor, | 2063 | .done = afs_fileserver_probe_result, |
2064 | .destructor = afs_destroy_fs_get_capabilities, | ||
2061 | }; | 2065 | }; |
2062 | 2066 | ||
2063 | /* | 2067 | /* |
@@ -2067,7 +2071,9 @@ static const struct afs_call_type afs_RXFSGetCapabilities = { | |||
2067 | int afs_fs_get_capabilities(struct afs_net *net, | 2071 | int afs_fs_get_capabilities(struct afs_net *net, |
2068 | struct afs_server *server, | 2072 | struct afs_server *server, |
2069 | struct afs_addr_cursor *ac, | 2073 | struct afs_addr_cursor *ac, |
2070 | struct key *key) | 2074 | struct key *key, |
2075 | unsigned int server_index, | ||
2076 | bool async) | ||
2071 | { | 2077 | { |
2072 | struct afs_call *call; | 2078 | struct afs_call *call; |
2073 | __be32 *bp; | 2079 | __be32 *bp; |
@@ -2079,6 +2085,10 @@ int afs_fs_get_capabilities(struct afs_net *net, | |||
2079 | return -ENOMEM; | 2085 | return -ENOMEM; |
2080 | 2086 | ||
2081 | call->key = key; | 2087 | call->key = key; |
2088 | call->reply[0] = afs_get_server(server); | ||
2089 | call->reply[1] = (void *)(long)server_index; | ||
2090 | call->upgrade = true; | ||
2091 | call->want_reply_time = true; | ||
2082 | 2092 | ||
2083 | /* marshall the parameters */ | 2093 | /* marshall the parameters */ |
2084 | bp = call->request; | 2094 | bp = call->request; |
@@ -2086,7 +2096,7 @@ int afs_fs_get_capabilities(struct afs_net *net, | |||
2086 | 2096 | ||
2087 | /* Can't take a ref on server */ | 2097 | /* Can't take a ref on server */ |
2088 | trace_afs_make_fs_call(call, NULL); | 2098 | trace_afs_make_fs_call(call, NULL); |
2089 | return afs_make_call(ac, call, GFP_NOFS, false); | 2099 | return afs_make_call(ac, call, GFP_NOFS, async); |
2090 | } | 2100 | } |
2091 | 2101 | ||
2092 | /* | 2102 | /* |
@@ -2097,7 +2107,7 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call) | |||
2097 | struct afs_file_status *status = call->reply[1]; | 2107 | struct afs_file_status *status = call->reply[1]; |
2098 | struct afs_callback *callback = call->reply[2]; | 2108 | struct afs_callback *callback = call->reply[2]; |
2099 | struct afs_volsync *volsync = call->reply[3]; | 2109 | struct afs_volsync *volsync = call->reply[3]; |
2100 | struct afs_vnode *vnode = call->reply[0]; | 2110 | struct afs_fid *fid = call->reply[0]; |
2101 | const __be32 *bp; | 2111 | const __be32 *bp; |
2102 | int ret; | 2112 | int ret; |
2103 | 2113 | ||
@@ -2105,21 +2115,16 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call) | |||
2105 | if (ret < 0) | 2115 | if (ret < 0) |
2106 | return ret; | 2116 | return ret; |
2107 | 2117 | ||
2108 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | 2118 | _enter("{%llx:%llu}", fid->vid, fid->vnode); |
2109 | 2119 | ||
2110 | /* unmarshall the reply once we've received all of it */ | 2120 | /* unmarshall the reply once we've received all of it */ |
2111 | bp = call->buffer; | 2121 | bp = call->buffer; |
2112 | afs_decode_status(call, &bp, status, vnode, | 2122 | ret = afs_decode_status(call, &bp, status, NULL, |
2113 | &call->expected_version, NULL); | 2123 | &call->expected_version, NULL); |
2114 | callback[call->count].version = ntohl(bp[0]); | 2124 | if (ret < 0) |
2115 | callback[call->count].expiry = ntohl(bp[1]); | 2125 | return ret; |
2116 | callback[call->count].type = ntohl(bp[2]); | 2126 | xdr_decode_AFSCallBack_raw(call, &bp, callback); |
2117 | if (vnode) | 2127 | xdr_decode_AFSVolSync(&bp, volsync); |
2118 | xdr_decode_AFSCallBack(call, vnode, &bp); | ||
2119 | else | ||
2120 | bp += 3; | ||
2121 | if (volsync) | ||
2122 | xdr_decode_AFSVolSync(&bp, volsync); | ||
2123 | 2128 | ||
2124 | _leave(" = 0 [done]"); | 2129 | _leave(" = 0 [done]"); |
2125 | return 0; | 2130 | return 0; |
@@ -2148,7 +2153,10 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
2148 | struct afs_call *call; | 2153 | struct afs_call *call; |
2149 | __be32 *bp; | 2154 | __be32 *bp; |
2150 | 2155 | ||
2151 | _enter(",%x,{%x:%u},,", | 2156 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
2157 | return yfs_fs_fetch_status(fc, net, fid, status, callback, volsync); | ||
2158 | |||
2159 | _enter(",%x,{%llx:%llu},,", | ||
2152 | key_serial(fc->key), fid->vid, fid->vnode); | 2160 | key_serial(fc->key), fid->vid, fid->vnode); |
2153 | 2161 | ||
2154 | call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); | 2162 | call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); |
@@ -2158,11 +2166,12 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
2158 | } | 2166 | } |
2159 | 2167 | ||
2160 | call->key = fc->key; | 2168 | call->key = fc->key; |
2161 | call->reply[0] = NULL; /* vnode for fid[0] */ | 2169 | call->reply[0] = fid; |
2162 | call->reply[1] = status; | 2170 | call->reply[1] = status; |
2163 | call->reply[2] = callback; | 2171 | call->reply[2] = callback; |
2164 | call->reply[3] = volsync; | 2172 | call->reply[3] = volsync; |
2165 | call->expected_version = 1; /* vnode->status.data_version */ | 2173 | call->expected_version = 1; /* vnode->status.data_version */ |
2174 | call->want_reply_time = true; | ||
2166 | 2175 | ||
2167 | /* marshall the parameters */ | 2176 | /* marshall the parameters */ |
2168 | bp = call->request; | 2177 | bp = call->request; |
@@ -2193,38 +2202,40 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
2193 | 2202 | ||
2194 | switch (call->unmarshall) { | 2203 | switch (call->unmarshall) { |
2195 | case 0: | 2204 | case 0: |
2196 | call->offset = 0; | 2205 | afs_extract_to_tmp(call); |
2197 | call->unmarshall++; | 2206 | call->unmarshall++; |
2198 | 2207 | ||
2199 | /* Extract the file status count and array in two steps */ | 2208 | /* Extract the file status count and array in two steps */ |
2200 | case 1: | 2209 | case 1: |
2201 | _debug("extract status count"); | 2210 | _debug("extract status count"); |
2202 | ret = afs_extract_data(call, &call->tmp, 4, true); | 2211 | ret = afs_extract_data(call, true); |
2203 | if (ret < 0) | 2212 | if (ret < 0) |
2204 | return ret; | 2213 | return ret; |
2205 | 2214 | ||
2206 | tmp = ntohl(call->tmp); | 2215 | tmp = ntohl(call->tmp); |
2207 | _debug("status count: %u/%u", tmp, call->count2); | 2216 | _debug("status count: %u/%u", tmp, call->count2); |
2208 | if (tmp != call->count2) | 2217 | if (tmp != call->count2) |
2209 | return afs_protocol_error(call, -EBADMSG); | 2218 | return afs_protocol_error(call, -EBADMSG, |
2219 | afs_eproto_ibulkst_count); | ||
2210 | 2220 | ||
2211 | call->count = 0; | 2221 | call->count = 0; |
2212 | call->unmarshall++; | 2222 | call->unmarshall++; |
2213 | more_counts: | 2223 | more_counts: |
2214 | call->offset = 0; | 2224 | afs_extract_to_buf(call, 21 * sizeof(__be32)); |
2215 | 2225 | ||
2216 | case 2: | 2226 | case 2: |
2217 | _debug("extract status array %u", call->count); | 2227 | _debug("extract status array %u", call->count); |
2218 | ret = afs_extract_data(call, call->buffer, 21 * 4, true); | 2228 | ret = afs_extract_data(call, true); |
2219 | if (ret < 0) | 2229 | if (ret < 0) |
2220 | return ret; | 2230 | return ret; |
2221 | 2231 | ||
2222 | bp = call->buffer; | 2232 | bp = call->buffer; |
2223 | statuses = call->reply[1]; | 2233 | statuses = call->reply[1]; |
2224 | if (afs_decode_status(call, &bp, &statuses[call->count], | 2234 | ret = afs_decode_status(call, &bp, &statuses[call->count], |
2225 | call->count == 0 ? vnode : NULL, | 2235 | call->count == 0 ? vnode : NULL, |
2226 | NULL, NULL) < 0) | 2236 | NULL, NULL); |
2227 | return afs_protocol_error(call, -EBADMSG); | 2237 | if (ret < 0) |
2238 | return ret; | ||
2228 | 2239 | ||
2229 | call->count++; | 2240 | call->count++; |
2230 | if (call->count < call->count2) | 2241 | if (call->count < call->count2) |
@@ -2232,27 +2243,28 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
2232 | 2243 | ||
2233 | call->count = 0; | 2244 | call->count = 0; |
2234 | call->unmarshall++; | 2245 | call->unmarshall++; |
2235 | call->offset = 0; | 2246 | afs_extract_to_tmp(call); |
2236 | 2247 | ||
2237 | /* Extract the callback count and array in two steps */ | 2248 | /* Extract the callback count and array in two steps */ |
2238 | case 3: | 2249 | case 3: |
2239 | _debug("extract CB count"); | 2250 | _debug("extract CB count"); |
2240 | ret = afs_extract_data(call, &call->tmp, 4, true); | 2251 | ret = afs_extract_data(call, true); |
2241 | if (ret < 0) | 2252 | if (ret < 0) |
2242 | return ret; | 2253 | return ret; |
2243 | 2254 | ||
2244 | tmp = ntohl(call->tmp); | 2255 | tmp = ntohl(call->tmp); |
2245 | _debug("CB count: %u", tmp); | 2256 | _debug("CB count: %u", tmp); |
2246 | if (tmp != call->count2) | 2257 | if (tmp != call->count2) |
2247 | return afs_protocol_error(call, -EBADMSG); | 2258 | return afs_protocol_error(call, -EBADMSG, |
2259 | afs_eproto_ibulkst_cb_count); | ||
2248 | call->count = 0; | 2260 | call->count = 0; |
2249 | call->unmarshall++; | 2261 | call->unmarshall++; |
2250 | more_cbs: | 2262 | more_cbs: |
2251 | call->offset = 0; | 2263 | afs_extract_to_buf(call, 3 * sizeof(__be32)); |
2252 | 2264 | ||
2253 | case 4: | 2265 | case 4: |
2254 | _debug("extract CB array"); | 2266 | _debug("extract CB array"); |
2255 | ret = afs_extract_data(call, call->buffer, 3 * 4, true); | 2267 | ret = afs_extract_data(call, true); |
2256 | if (ret < 0) | 2268 | if (ret < 0) |
2257 | return ret; | 2269 | return ret; |
2258 | 2270 | ||
@@ -2260,7 +2272,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
2260 | bp = call->buffer; | 2272 | bp = call->buffer; |
2261 | callbacks = call->reply[2]; | 2273 | callbacks = call->reply[2]; |
2262 | callbacks[call->count].version = ntohl(bp[0]); | 2274 | callbacks[call->count].version = ntohl(bp[0]); |
2263 | callbacks[call->count].expiry = ntohl(bp[1]); | 2275 | callbacks[call->count].expires_at = xdr_decode_expiry(call, ntohl(bp[1])); |
2264 | callbacks[call->count].type = ntohl(bp[2]); | 2276 | callbacks[call->count].type = ntohl(bp[2]); |
2265 | statuses = call->reply[1]; | 2277 | statuses = call->reply[1]; |
2266 | if (call->count == 0 && vnode && statuses[0].abort_code == 0) | 2278 | if (call->count == 0 && vnode && statuses[0].abort_code == 0) |
@@ -2269,19 +2281,17 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
2269 | if (call->count < call->count2) | 2281 | if (call->count < call->count2) |
2270 | goto more_cbs; | 2282 | goto more_cbs; |
2271 | 2283 | ||
2272 | call->offset = 0; | 2284 | afs_extract_to_buf(call, 6 * sizeof(__be32)); |
2273 | call->unmarshall++; | 2285 | call->unmarshall++; |
2274 | 2286 | ||
2275 | case 5: | 2287 | case 5: |
2276 | ret = afs_extract_data(call, call->buffer, 6 * 4, false); | 2288 | ret = afs_extract_data(call, false); |
2277 | if (ret < 0) | 2289 | if (ret < 0) |
2278 | return ret; | 2290 | return ret; |
2279 | 2291 | ||
2280 | bp = call->buffer; | 2292 | bp = call->buffer; |
2281 | if (call->reply[3]) | 2293 | xdr_decode_AFSVolSync(&bp, call->reply[3]); |
2282 | xdr_decode_AFSVolSync(&bp, call->reply[3]); | ||
2283 | 2294 | ||
2284 | call->offset = 0; | ||
2285 | call->unmarshall++; | 2295 | call->unmarshall++; |
2286 | 2296 | ||
2287 | case 6: | 2297 | case 6: |
@@ -2317,7 +2327,11 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
2317 | __be32 *bp; | 2327 | __be32 *bp; |
2318 | int i; | 2328 | int i; |
2319 | 2329 | ||
2320 | _enter(",%x,{%x:%u},%u", | 2330 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
2331 | return yfs_fs_inline_bulk_status(fc, net, fids, statuses, callbacks, | ||
2332 | nr_fids, volsync); | ||
2333 | |||
2334 | _enter(",%x,{%llx:%llu},%u", | ||
2321 | key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); | 2335 | key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); |
2322 | 2336 | ||
2323 | call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus, | 2337 | call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus, |
@@ -2334,6 +2348,7 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
2334 | call->reply[2] = callbacks; | 2348 | call->reply[2] = callbacks; |
2335 | call->reply[3] = volsync; | 2349 | call->reply[3] = volsync; |
2336 | call->count2 = nr_fids; | 2350 | call->count2 = nr_fids; |
2351 | call->want_reply_time = true; | ||
2337 | 2352 | ||
2338 | /* marshall the parameters */ | 2353 | /* marshall the parameters */ |
2339 | bp = call->request; | 2354 | bp = call->request; |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 479b7fdda124..4c6d8e1112c2 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
@@ -82,7 +82,7 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key) | |||
82 | default: | 82 | default: |
83 | printk("kAFS: AFS vnode with undefined type\n"); | 83 | printk("kAFS: AFS vnode with undefined type\n"); |
84 | read_sequnlock_excl(&vnode->cb_lock); | 84 | read_sequnlock_excl(&vnode->cb_lock); |
85 | return afs_protocol_error(NULL, -EBADMSG); | 85 | return afs_protocol_error(NULL, -EBADMSG, afs_eproto_file_type); |
86 | } | 86 | } |
87 | 87 | ||
88 | inode->i_blocks = 0; | 88 | inode->i_blocks = 0; |
@@ -100,7 +100,7 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode) | |||
100 | struct afs_fs_cursor fc; | 100 | struct afs_fs_cursor fc; |
101 | int ret; | 101 | int ret; |
102 | 102 | ||
103 | _enter("%s,{%x:%u.%u,S=%lx}", | 103 | _enter("%s,{%llx:%llu.%u,S=%lx}", |
104 | vnode->volume->name, | 104 | vnode->volume->name, |
105 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique, | 105 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique, |
106 | vnode->flags); | 106 | vnode->flags); |
@@ -127,9 +127,9 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode) | |||
127 | int afs_iget5_test(struct inode *inode, void *opaque) | 127 | int afs_iget5_test(struct inode *inode, void *opaque) |
128 | { | 128 | { |
129 | struct afs_iget_data *data = opaque; | 129 | struct afs_iget_data *data = opaque; |
130 | struct afs_vnode *vnode = AFS_FS_I(inode); | ||
130 | 131 | ||
131 | return inode->i_ino == data->fid.vnode && | 132 | return memcmp(&vnode->fid, &data->fid, sizeof(data->fid)) == 0; |
132 | inode->i_generation == data->fid.unique; | ||
133 | } | 133 | } |
134 | 134 | ||
135 | /* | 135 | /* |
@@ -150,11 +150,14 @@ static int afs_iget5_set(struct inode *inode, void *opaque) | |||
150 | struct afs_iget_data *data = opaque; | 150 | struct afs_iget_data *data = opaque; |
151 | struct afs_vnode *vnode = AFS_FS_I(inode); | 151 | struct afs_vnode *vnode = AFS_FS_I(inode); |
152 | 152 | ||
153 | inode->i_ino = data->fid.vnode; | ||
154 | inode->i_generation = data->fid.unique; | ||
155 | vnode->fid = data->fid; | 153 | vnode->fid = data->fid; |
156 | vnode->volume = data->volume; | 154 | vnode->volume = data->volume; |
157 | 155 | ||
156 | /* YFS supports 96-bit vnode IDs, but Linux only supports | ||
157 | * 64-bit inode numbers. | ||
158 | */ | ||
159 | inode->i_ino = data->fid.vnode; | ||
160 | inode->i_generation = data->fid.unique; | ||
158 | return 0; | 161 | return 0; |
159 | } | 162 | } |
160 | 163 | ||
@@ -193,7 +196,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root) | |||
193 | return ERR_PTR(-ENOMEM); | 196 | return ERR_PTR(-ENOMEM); |
194 | } | 197 | } |
195 | 198 | ||
196 | _debug("GOT INODE %p { ino=%lu, vl=%x, vn=%x, u=%x }", | 199 | _debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }", |
197 | inode, inode->i_ino, data.fid.vid, data.fid.vnode, | 200 | inode, inode->i_ino, data.fid.vid, data.fid.vnode, |
198 | data.fid.unique); | 201 | data.fid.unique); |
199 | 202 | ||
@@ -252,8 +255,8 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) | |||
252 | 255 | ||
253 | key.vnode_id = vnode->fid.vnode; | 256 | key.vnode_id = vnode->fid.vnode; |
254 | key.unique = vnode->fid.unique; | 257 | key.unique = vnode->fid.unique; |
255 | key.vnode_id_ext[0] = 0; | 258 | key.vnode_id_ext[0] = vnode->fid.vnode >> 32; |
256 | key.vnode_id_ext[1] = 0; | 259 | key.vnode_id_ext[1] = vnode->fid.vnode_hi; |
257 | aux.data_version = vnode->status.data_version; | 260 | aux.data_version = vnode->status.data_version; |
258 | 261 | ||
259 | vnode->cache = fscache_acquire_cookie(vnode->volume->cache, | 262 | vnode->cache = fscache_acquire_cookie(vnode->volume->cache, |
@@ -277,7 +280,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key, | |||
277 | struct inode *inode; | 280 | struct inode *inode; |
278 | int ret; | 281 | int ret; |
279 | 282 | ||
280 | _enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique); | 283 | _enter(",{%llx:%llu.%u},,", fid->vid, fid->vnode, fid->unique); |
281 | 284 | ||
282 | as = sb->s_fs_info; | 285 | as = sb->s_fs_info; |
283 | data.volume = as->volume; | 286 | data.volume = as->volume; |
@@ -289,7 +292,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key, | |||
289 | return ERR_PTR(-ENOMEM); | 292 | return ERR_PTR(-ENOMEM); |
290 | } | 293 | } |
291 | 294 | ||
292 | _debug("GOT INODE %p { vl=%x vn=%x, u=%x }", | 295 | _debug("GOT INODE %p { vl=%llx vn=%llx, u=%x }", |
293 | inode, fid->vid, fid->vnode, fid->unique); | 296 | inode, fid->vid, fid->vnode, fid->unique); |
294 | 297 | ||
295 | vnode = AFS_FS_I(inode); | 298 | vnode = AFS_FS_I(inode); |
@@ -314,11 +317,11 @@ struct inode *afs_iget(struct super_block *sb, struct key *key, | |||
314 | * didn't give us a callback) */ | 317 | * didn't give us a callback) */ |
315 | vnode->cb_version = 0; | 318 | vnode->cb_version = 0; |
316 | vnode->cb_type = 0; | 319 | vnode->cb_type = 0; |
317 | vnode->cb_expires_at = 0; | 320 | vnode->cb_expires_at = ktime_get(); |
318 | } else { | 321 | } else { |
319 | vnode->cb_version = cb->version; | 322 | vnode->cb_version = cb->version; |
320 | vnode->cb_type = cb->type; | 323 | vnode->cb_type = cb->type; |
321 | vnode->cb_expires_at = cb->expiry; | 324 | vnode->cb_expires_at = cb->expires_at; |
322 | vnode->cb_interest = afs_get_cb_interest(cbi); | 325 | vnode->cb_interest = afs_get_cb_interest(cbi); |
323 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | 326 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); |
324 | } | 327 | } |
@@ -352,7 +355,7 @@ bad_inode: | |||
352 | */ | 355 | */ |
353 | void afs_zap_data(struct afs_vnode *vnode) | 356 | void afs_zap_data(struct afs_vnode *vnode) |
354 | { | 357 | { |
355 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | 358 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); |
356 | 359 | ||
357 | #ifdef CONFIG_AFS_FSCACHE | 360 | #ifdef CONFIG_AFS_FSCACHE |
358 | fscache_invalidate(vnode->cache); | 361 | fscache_invalidate(vnode->cache); |
@@ -382,7 +385,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
382 | bool valid = false; | 385 | bool valid = false; |
383 | int ret; | 386 | int ret; |
384 | 387 | ||
385 | _enter("{v={%x:%u} fl=%lx},%x", | 388 | _enter("{v={%llx:%llu} fl=%lx},%x", |
386 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, | 389 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, |
387 | key_serial(key)); | 390 | key_serial(key)); |
388 | 391 | ||
@@ -501,7 +504,7 @@ void afs_evict_inode(struct inode *inode) | |||
501 | 504 | ||
502 | vnode = AFS_FS_I(inode); | 505 | vnode = AFS_FS_I(inode); |
503 | 506 | ||
504 | _enter("{%x:%u.%d}", | 507 | _enter("{%llx:%llu.%d}", |
505 | vnode->fid.vid, | 508 | vnode->fid.vid, |
506 | vnode->fid.vnode, | 509 | vnode->fid.vnode, |
507 | vnode->fid.unique); | 510 | vnode->fid.unique); |
@@ -550,7 +553,7 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr) | |||
550 | struct key *key; | 553 | struct key *key; |
551 | int ret; | 554 | int ret; |
552 | 555 | ||
553 | _enter("{%x:%u},{n=%pd},%x", | 556 | _enter("{%llx:%llu},{n=%pd},%x", |
554 | vnode->fid.vid, vnode->fid.vnode, dentry, | 557 | vnode->fid.vid, vnode->fid.vnode, dentry, |
555 | attr->ia_valid); | 558 | attr->ia_valid); |
556 | 559 | ||
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 72de1f157d20..5da3b09b7518 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/backing-dev.h> | 22 | #include <linux/backing-dev.h> |
23 | #include <linux/uuid.h> | 23 | #include <linux/uuid.h> |
24 | #include <linux/mm_types.h> | 24 | #include <linux/mm_types.h> |
25 | #include <linux/dns_resolver.h> | ||
25 | #include <net/net_namespace.h> | 26 | #include <net/net_namespace.h> |
26 | #include <net/netns/generic.h> | 27 | #include <net/netns/generic.h> |
27 | #include <net/sock.h> | 28 | #include <net/sock.h> |
@@ -75,10 +76,13 @@ struct afs_addr_list { | |||
75 | u32 version; /* Version */ | 76 | u32 version; /* Version */ |
76 | unsigned char max_addrs; | 77 | unsigned char max_addrs; |
77 | unsigned char nr_addrs; | 78 | unsigned char nr_addrs; |
78 | unsigned char index; /* Address currently in use */ | 79 | unsigned char preferred; /* Preferred address */ |
79 | unsigned char nr_ipv4; /* Number of IPv4 addresses */ | 80 | unsigned char nr_ipv4; /* Number of IPv4 addresses */ |
81 | enum dns_record_source source:8; | ||
82 | enum dns_lookup_status status:8; | ||
80 | unsigned long probed; /* Mask of servers that have been probed */ | 83 | unsigned long probed; /* Mask of servers that have been probed */ |
81 | unsigned long yfs; /* Mask of servers that are YFS */ | 84 | unsigned long failed; /* Mask of addrs that failed locally/ICMP */ |
85 | unsigned long responded; /* Mask of addrs that responded */ | ||
82 | struct sockaddr_rxrpc addrs[]; | 86 | struct sockaddr_rxrpc addrs[]; |
83 | #define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8)) | 87 | #define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8)) |
84 | }; | 88 | }; |
@@ -88,6 +92,7 @@ struct afs_addr_list { | |||
88 | */ | 92 | */ |
89 | struct afs_call { | 93 | struct afs_call { |
90 | const struct afs_call_type *type; /* type of call */ | 94 | const struct afs_call_type *type; /* type of call */ |
95 | struct afs_addr_list *alist; /* Address is alist[addr_ix] */ | ||
91 | wait_queue_head_t waitq; /* processes awaiting completion */ | 96 | wait_queue_head_t waitq; /* processes awaiting completion */ |
92 | struct work_struct async_work; /* async I/O processor */ | 97 | struct work_struct async_work; /* async I/O processor */ |
93 | struct work_struct work; /* actual work processor */ | 98 | struct work_struct work; /* actual work processor */ |
@@ -98,16 +103,22 @@ struct afs_call { | |||
98 | struct afs_cb_interest *cbi; /* Callback interest for server used */ | 103 | struct afs_cb_interest *cbi; /* Callback interest for server used */ |
99 | void *request; /* request data (first part) */ | 104 | void *request; /* request data (first part) */ |
100 | struct address_space *mapping; /* Pages being written from */ | 105 | struct address_space *mapping; /* Pages being written from */ |
106 | struct iov_iter iter; /* Buffer iterator */ | ||
107 | struct iov_iter *_iter; /* Iterator currently in use */ | ||
108 | union { /* Convenience for ->iter */ | ||
109 | struct kvec kvec[1]; | ||
110 | struct bio_vec bvec[1]; | ||
111 | }; | ||
101 | void *buffer; /* reply receive buffer */ | 112 | void *buffer; /* reply receive buffer */ |
102 | void *reply[4]; /* Where to put the reply */ | 113 | void *reply[4]; /* Where to put the reply */ |
103 | pgoff_t first; /* first page in mapping to deal with */ | 114 | pgoff_t first; /* first page in mapping to deal with */ |
104 | pgoff_t last; /* last page in mapping to deal with */ | 115 | pgoff_t last; /* last page in mapping to deal with */ |
105 | size_t offset; /* offset into received data store */ | ||
106 | atomic_t usage; | 116 | atomic_t usage; |
107 | enum afs_call_state state; | 117 | enum afs_call_state state; |
108 | spinlock_t state_lock; | 118 | spinlock_t state_lock; |
109 | int error; /* error code */ | 119 | int error; /* error code */ |
110 | u32 abort_code; /* Remote abort ID or 0 */ | 120 | u32 abort_code; /* Remote abort ID or 0 */ |
121 | u32 epoch; | ||
111 | unsigned request_size; /* size of request data */ | 122 | unsigned request_size; /* size of request data */ |
112 | unsigned reply_max; /* maximum size of reply */ | 123 | unsigned reply_max; /* maximum size of reply */ |
113 | unsigned first_offset; /* offset into mapping[first] */ | 124 | unsigned first_offset; /* offset into mapping[first] */ |
@@ -117,19 +128,28 @@ struct afs_call { | |||
117 | unsigned count2; /* count used in unmarshalling */ | 128 | unsigned count2; /* count used in unmarshalling */ |
118 | }; | 129 | }; |
119 | unsigned char unmarshall; /* unmarshalling phase */ | 130 | unsigned char unmarshall; /* unmarshalling phase */ |
131 | unsigned char addr_ix; /* Address in ->alist */ | ||
120 | bool incoming; /* T if incoming call */ | 132 | bool incoming; /* T if incoming call */ |
121 | bool send_pages; /* T if data from mapping should be sent */ | 133 | bool send_pages; /* T if data from mapping should be sent */ |
122 | bool need_attention; /* T if RxRPC poked us */ | 134 | bool need_attention; /* T if RxRPC poked us */ |
123 | bool async; /* T if asynchronous */ | 135 | bool async; /* T if asynchronous */ |
124 | bool ret_reply0; /* T if should return reply[0] on success */ | 136 | bool ret_reply0; /* T if should return reply[0] on success */ |
125 | bool upgrade; /* T to request service upgrade */ | 137 | bool upgrade; /* T to request service upgrade */ |
138 | bool want_reply_time; /* T if want reply_time */ | ||
126 | u16 service_id; /* Actual service ID (after upgrade) */ | 139 | u16 service_id; /* Actual service ID (after upgrade) */ |
127 | unsigned int debug_id; /* Trace ID */ | 140 | unsigned int debug_id; /* Trace ID */ |
128 | u32 operation_ID; /* operation ID for an incoming call */ | 141 | u32 operation_ID; /* operation ID for an incoming call */ |
129 | u32 count; /* count for use in unmarshalling */ | 142 | u32 count; /* count for use in unmarshalling */ |
130 | __be32 tmp; /* place to extract temporary data */ | 143 | union { /* place to extract temporary data */ |
144 | struct { | ||
145 | __be32 tmp_u; | ||
146 | __be32 tmp; | ||
147 | } __attribute__((packed)); | ||
148 | __be64 tmp64; | ||
149 | }; | ||
131 | afs_dataversion_t expected_version; /* Updated version expected from store */ | 150 | afs_dataversion_t expected_version; /* Updated version expected from store */ |
132 | afs_dataversion_t expected_version_2; /* 2nd updated version expected from store */ | 151 | afs_dataversion_t expected_version_2; /* 2nd updated version expected from store */ |
152 | ktime_t reply_time; /* Time of first reply packet */ | ||
133 | }; | 153 | }; |
134 | 154 | ||
135 | struct afs_call_type { | 155 | struct afs_call_type { |
@@ -146,6 +166,9 @@ struct afs_call_type { | |||
146 | 166 | ||
147 | /* Work function */ | 167 | /* Work function */ |
148 | void (*work)(struct work_struct *work); | 168 | void (*work)(struct work_struct *work); |
169 | |||
170 | /* Call done function (gets called immediately on success or failure) */ | ||
171 | void (*done)(struct afs_call *call); | ||
149 | }; | 172 | }; |
150 | 173 | ||
151 | /* | 174 | /* |
@@ -185,6 +208,7 @@ struct afs_read { | |||
185 | refcount_t usage; | 208 | refcount_t usage; |
186 | unsigned int index; /* Which page we're reading into */ | 209 | unsigned int index; /* Which page we're reading into */ |
187 | unsigned int nr_pages; | 210 | unsigned int nr_pages; |
211 | unsigned int offset; /* offset into current page */ | ||
188 | void (*page_done)(struct afs_call *, struct afs_read *); | 212 | void (*page_done)(struct afs_call *, struct afs_read *); |
189 | struct page **pages; | 213 | struct page **pages; |
190 | struct page *array[]; | 214 | struct page *array[]; |
@@ -343,13 +367,70 @@ struct afs_cell { | |||
343 | rwlock_t proc_lock; | 367 | rwlock_t proc_lock; |
344 | 368 | ||
345 | /* VL server list. */ | 369 | /* VL server list. */ |
346 | rwlock_t vl_addrs_lock; /* Lock on vl_addrs */ | 370 | rwlock_t vl_servers_lock; /* Lock on vl_servers */ |
347 | struct afs_addr_list __rcu *vl_addrs; /* List of VL servers */ | 371 | struct afs_vlserver_list __rcu *vl_servers; |
372 | |||
348 | u8 name_len; /* Length of name */ | 373 | u8 name_len; /* Length of name */ |
349 | char name[64 + 1]; /* Cell name, case-flattened and NUL-padded */ | 374 | char name[64 + 1]; /* Cell name, case-flattened and NUL-padded */ |
350 | }; | 375 | }; |
351 | 376 | ||
352 | /* | 377 | /* |
378 | * Volume Location server record. | ||
379 | */ | ||
380 | struct afs_vlserver { | ||
381 | struct rcu_head rcu; | ||
382 | struct afs_addr_list __rcu *addresses; /* List of addresses for this VL server */ | ||
383 | unsigned long flags; | ||
384 | #define AFS_VLSERVER_FL_PROBED 0 /* The VL server has been probed */ | ||
385 | #define AFS_VLSERVER_FL_PROBING 1 /* VL server is being probed */ | ||
386 | #define AFS_VLSERVER_FL_IS_YFS 2 /* Server is YFS not AFS */ | ||
387 | rwlock_t lock; /* Lock on addresses */ | ||
388 | atomic_t usage; | ||
389 | |||
390 | /* Probe state */ | ||
391 | wait_queue_head_t probe_wq; | ||
392 | atomic_t probe_outstanding; | ||
393 | spinlock_t probe_lock; | ||
394 | struct { | ||
395 | unsigned int rtt; /* RTT as ktime/64 */ | ||
396 | u32 abort_code; | ||
397 | short error; | ||
398 | bool have_result; | ||
399 | bool responded:1; | ||
400 | bool is_yfs:1; | ||
401 | bool not_yfs:1; | ||
402 | bool local_failure:1; | ||
403 | } probe; | ||
404 | |||
405 | u16 port; | ||
406 | u16 name_len; /* Length of name */ | ||
407 | char name[]; /* Server name, case-flattened */ | ||
408 | }; | ||
409 | |||
410 | /* | ||
411 | * Weighted list of Volume Location servers. | ||
412 | */ | ||
413 | struct afs_vlserver_entry { | ||
414 | u16 priority; /* Preference (as SRV) */ | ||
415 | u16 weight; /* Weight (as SRV) */ | ||
416 | enum dns_record_source source:8; | ||
417 | enum dns_lookup_status status:8; | ||
418 | struct afs_vlserver *server; | ||
419 | }; | ||
420 | |||
421 | struct afs_vlserver_list { | ||
422 | struct rcu_head rcu; | ||
423 | atomic_t usage; | ||
424 | u8 nr_servers; | ||
425 | u8 index; /* Server currently in use */ | ||
426 | u8 preferred; /* Preferred server */ | ||
427 | enum dns_record_source source:8; | ||
428 | enum dns_lookup_status status:8; | ||
429 | rwlock_t lock; | ||
430 | struct afs_vlserver_entry servers[]; | ||
431 | }; | ||
432 | |||
433 | /* | ||
353 | * Cached VLDB entry. | 434 | * Cached VLDB entry. |
354 | * | 435 | * |
355 | * This is pointed to by cell->vldb_entries, indexed by name. | 436 | * This is pointed to by cell->vldb_entries, indexed by name. |
@@ -403,8 +484,12 @@ struct afs_server { | |||
403 | #define AFS_SERVER_FL_PROBING 6 /* Fileserver is being probed */ | 484 | #define AFS_SERVER_FL_PROBING 6 /* Fileserver is being probed */ |
404 | #define AFS_SERVER_FL_NO_IBULK 7 /* Fileserver doesn't support FS.InlineBulkStatus */ | 485 | #define AFS_SERVER_FL_NO_IBULK 7 /* Fileserver doesn't support FS.InlineBulkStatus */ |
405 | #define AFS_SERVER_FL_MAY_HAVE_CB 8 /* May have callbacks on this fileserver */ | 486 | #define AFS_SERVER_FL_MAY_HAVE_CB 8 /* May have callbacks on this fileserver */ |
487 | #define AFS_SERVER_FL_IS_YFS 9 /* Server is YFS not AFS */ | ||
488 | #define AFS_SERVER_FL_NO_RM2 10 /* Fileserver doesn't support YFS.RemoveFile2 */ | ||
489 | #define AFS_SERVER_FL_HAVE_EPOCH 11 /* ->epoch is valid */ | ||
406 | atomic_t usage; | 490 | atomic_t usage; |
407 | u32 addr_version; /* Address list version */ | 491 | u32 addr_version; /* Address list version */ |
492 | u32 cm_epoch; /* Server RxRPC epoch */ | ||
408 | 493 | ||
409 | /* file service access */ | 494 | /* file service access */ |
410 | rwlock_t fs_lock; /* access lock */ | 495 | rwlock_t fs_lock; /* access lock */ |
@@ -413,6 +498,26 @@ struct afs_server { | |||
413 | struct hlist_head cb_volumes; /* List of volume interests on this server */ | 498 | struct hlist_head cb_volumes; /* List of volume interests on this server */ |
414 | unsigned cb_s_break; /* Break-everything counter. */ | 499 | unsigned cb_s_break; /* Break-everything counter. */ |
415 | rwlock_t cb_break_lock; /* Volume finding lock */ | 500 | rwlock_t cb_break_lock; /* Volume finding lock */ |
501 | |||
502 | /* Probe state */ | ||
503 | wait_queue_head_t probe_wq; | ||
504 | atomic_t probe_outstanding; | ||
505 | spinlock_t probe_lock; | ||
506 | struct { | ||
507 | unsigned int rtt; /* RTT as ktime/64 */ | ||
508 | u32 abort_code; | ||
509 | u32 cm_epoch; | ||
510 | short error; | ||
511 | bool have_result; | ||
512 | bool responded:1; | ||
513 | bool is_yfs:1; | ||
514 | bool not_yfs:1; | ||
515 | bool local_failure:1; | ||
516 | bool no_epoch:1; | ||
517 | bool cm_probed:1; | ||
518 | bool said_rebooted:1; | ||
519 | bool said_inconsistent:1; | ||
520 | } probe; | ||
416 | }; | 521 | }; |
417 | 522 | ||
418 | /* | 523 | /* |
@@ -447,8 +552,8 @@ struct afs_server_entry { | |||
447 | 552 | ||
448 | struct afs_server_list { | 553 | struct afs_server_list { |
449 | refcount_t usage; | 554 | refcount_t usage; |
450 | unsigned short nr_servers; | 555 | unsigned char nr_servers; |
451 | unsigned short index; /* Server currently in use */ | 556 | unsigned char preferred; /* Preferred server */ |
452 | unsigned short vnovol_mask; /* Servers to be skipped due to VNOVOL */ | 557 | unsigned short vnovol_mask; /* Servers to be skipped due to VNOVOL */ |
453 | unsigned int seq; /* Set to ->servers_seq when installed */ | 558 | unsigned int seq; /* Set to ->servers_seq when installed */ |
454 | rwlock_t lock; | 559 | rwlock_t lock; |
@@ -550,6 +655,15 @@ struct afs_vnode { | |||
550 | afs_callback_type_t cb_type; /* type of callback */ | 655 | afs_callback_type_t cb_type; /* type of callback */ |
551 | }; | 656 | }; |
552 | 657 | ||
658 | static inline struct fscache_cookie *afs_vnode_cache(struct afs_vnode *vnode) | ||
659 | { | ||
660 | #ifdef CONFIG_AFS_FSCACHE | ||
661 | return vnode->cache; | ||
662 | #else | ||
663 | return NULL; | ||
664 | #endif | ||
665 | } | ||
666 | |||
553 | /* | 667 | /* |
554 | * cached security record for one user's attempt to access a vnode | 668 | * cached security record for one user's attempt to access a vnode |
555 | */ | 669 | */ |
@@ -586,13 +700,31 @@ struct afs_interface { | |||
586 | */ | 700 | */ |
587 | struct afs_addr_cursor { | 701 | struct afs_addr_cursor { |
588 | struct afs_addr_list *alist; /* Current address list (pins ref) */ | 702 | struct afs_addr_list *alist; /* Current address list (pins ref) */ |
589 | struct sockaddr_rxrpc *addr; | 703 | unsigned long tried; /* Tried addresses */ |
704 | signed char index; /* Current address */ | ||
705 | bool responded; /* T if the current address responded */ | ||
706 | unsigned short nr_iterations; /* Number of address iterations */ | ||
707 | short error; | ||
590 | u32 abort_code; | 708 | u32 abort_code; |
591 | unsigned short start; /* Starting point in alist->addrs[] */ | 709 | }; |
592 | unsigned short index; /* Wrapping offset from start to current addr */ | 710 | |
711 | /* | ||
712 | * Cursor for iterating over a set of volume location servers. | ||
713 | */ | ||
714 | struct afs_vl_cursor { | ||
715 | struct afs_addr_cursor ac; | ||
716 | struct afs_cell *cell; /* The cell we're querying */ | ||
717 | struct afs_vlserver_list *server_list; /* Current server list (pins ref) */ | ||
718 | struct afs_vlserver *server; /* Server on which this resides */ | ||
719 | struct key *key; /* Key for the server */ | ||
720 | unsigned long untried; /* Bitmask of untried servers */ | ||
721 | short index; /* Current server */ | ||
593 | short error; | 722 | short error; |
594 | bool begun; /* T if we've begun iteration */ | 723 | unsigned short flags; |
595 | bool responded; /* T if the current address responded */ | 724 | #define AFS_VL_CURSOR_STOP 0x0001 /* Set to cease iteration */ |
725 | #define AFS_VL_CURSOR_RETRY 0x0002 /* Set to do a retry */ | ||
726 | #define AFS_VL_CURSOR_RETRIED 0x0004 /* Set if started a retry */ | ||
727 | unsigned short nr_iterations; /* Number of server iterations */ | ||
596 | }; | 728 | }; |
597 | 729 | ||
598 | /* | 730 | /* |
@@ -604,10 +736,11 @@ struct afs_fs_cursor { | |||
604 | struct afs_server_list *server_list; /* Current server list (pins ref) */ | 736 | struct afs_server_list *server_list; /* Current server list (pins ref) */ |
605 | struct afs_cb_interest *cbi; /* Server on which this resides (pins ref) */ | 737 | struct afs_cb_interest *cbi; /* Server on which this resides (pins ref) */ |
606 | struct key *key; /* Key for the server */ | 738 | struct key *key; /* Key for the server */ |
739 | unsigned long untried; /* Bitmask of untried servers */ | ||
607 | unsigned int cb_break; /* cb_break + cb_s_break before the call */ | 740 | unsigned int cb_break; /* cb_break + cb_s_break before the call */ |
608 | unsigned int cb_break_2; /* cb_break + cb_s_break (2nd vnode) */ | 741 | unsigned int cb_break_2; /* cb_break + cb_s_break (2nd vnode) */ |
609 | unsigned char start; /* Initial index in server list */ | 742 | short index; /* Current server */ |
610 | unsigned char index; /* Number of servers tried beyond start */ | 743 | short error; |
611 | unsigned short flags; | 744 | unsigned short flags; |
612 | #define AFS_FS_CURSOR_STOP 0x0001 /* Set to cease iteration */ | 745 | #define AFS_FS_CURSOR_STOP 0x0001 /* Set to cease iteration */ |
613 | #define AFS_FS_CURSOR_VBUSY 0x0002 /* Set if seen VBUSY */ | 746 | #define AFS_FS_CURSOR_VBUSY 0x0002 /* Set if seen VBUSY */ |
@@ -615,6 +748,7 @@ struct afs_fs_cursor { | |||
615 | #define AFS_FS_CURSOR_VNOVOL 0x0008 /* Set if seen VNOVOL */ | 748 | #define AFS_FS_CURSOR_VNOVOL 0x0008 /* Set if seen VNOVOL */ |
616 | #define AFS_FS_CURSOR_CUR_ONLY 0x0010 /* Set if current server only (file lock held) */ | 749 | #define AFS_FS_CURSOR_CUR_ONLY 0x0010 /* Set if current server only (file lock held) */ |
617 | #define AFS_FS_CURSOR_NO_VSLEEP 0x0020 /* Set to prevent sleep on VBUSY, VOFFLINE, ... */ | 750 | #define AFS_FS_CURSOR_NO_VSLEEP 0x0020 /* Set to prevent sleep on VBUSY, VOFFLINE, ... */ |
751 | unsigned short nr_iterations; /* Number of server iterations */ | ||
618 | }; | 752 | }; |
619 | 753 | ||
620 | /* | 754 | /* |
@@ -640,12 +774,12 @@ extern struct afs_addr_list *afs_alloc_addrlist(unsigned int, | |||
640 | unsigned short, | 774 | unsigned short, |
641 | unsigned short); | 775 | unsigned short); |
642 | extern void afs_put_addrlist(struct afs_addr_list *); | 776 | extern void afs_put_addrlist(struct afs_addr_list *); |
643 | extern struct afs_addr_list *afs_parse_text_addrs(const char *, size_t, char, | 777 | extern struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *, |
644 | unsigned short, unsigned short); | 778 | const char *, size_t, char, |
645 | extern struct afs_addr_list *afs_dns_query(struct afs_cell *, time64_t *); | 779 | unsigned short, unsigned short); |
780 | extern struct afs_vlserver_list *afs_dns_query(struct afs_cell *, time64_t *); | ||
646 | extern bool afs_iterate_addresses(struct afs_addr_cursor *); | 781 | extern bool afs_iterate_addresses(struct afs_addr_cursor *); |
647 | extern int afs_end_cursor(struct afs_addr_cursor *); | 782 | extern int afs_end_cursor(struct afs_addr_cursor *); |
648 | extern int afs_set_vl_cursor(struct afs_addr_cursor *, struct afs_cell *); | ||
649 | 783 | ||
650 | extern void afs_merge_fs_addr4(struct afs_addr_list *, __be32, u16); | 784 | extern void afs_merge_fs_addr4(struct afs_addr_list *, __be32, u16); |
651 | extern void afs_merge_fs_addr6(struct afs_addr_list *, __be32 *, u16); | 785 | extern void afs_merge_fs_addr6(struct afs_addr_list *, __be32 *, u16); |
@@ -668,6 +802,7 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def; | |||
668 | * callback.c | 802 | * callback.c |
669 | */ | 803 | */ |
670 | extern void afs_init_callback_state(struct afs_server *); | 804 | extern void afs_init_callback_state(struct afs_server *); |
805 | extern void __afs_break_callback(struct afs_vnode *); | ||
671 | extern void afs_break_callback(struct afs_vnode *); | 806 | extern void afs_break_callback(struct afs_vnode *); |
672 | extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*); | 807 | extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*); |
673 | 808 | ||
@@ -688,10 +823,13 @@ static inline unsigned int afs_calc_vnode_cb_break(struct afs_vnode *vnode) | |||
688 | return vnode->cb_break + vnode->cb_s_break + vnode->cb_v_break; | 823 | return vnode->cb_break + vnode->cb_s_break + vnode->cb_v_break; |
689 | } | 824 | } |
690 | 825 | ||
691 | static inline unsigned int afs_cb_break_sum(struct afs_vnode *vnode, | 826 | static inline bool afs_cb_is_broken(unsigned int cb_break, |
692 | struct afs_cb_interest *cbi) | 827 | const struct afs_vnode *vnode, |
828 | const struct afs_cb_interest *cbi) | ||
693 | { | 829 | { |
694 | return vnode->cb_break + cbi->server->cb_s_break + vnode->volume->cb_v_break; | 830 | return !cbi || cb_break != (vnode->cb_break + |
831 | cbi->server->cb_s_break + | ||
832 | vnode->volume->cb_v_break); | ||
695 | } | 833 | } |
696 | 834 | ||
697 | /* | 835 | /* |
@@ -781,7 +919,7 @@ extern int afs_fs_give_up_callbacks(struct afs_net *, struct afs_server *); | |||
781 | extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *); | 919 | extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *); |
782 | extern int afs_fs_create(struct afs_fs_cursor *, const char *, umode_t, u64, | 920 | extern int afs_fs_create(struct afs_fs_cursor *, const char *, umode_t, u64, |
783 | struct afs_fid *, struct afs_file_status *, struct afs_callback *); | 921 | struct afs_fid *, struct afs_file_status *, struct afs_callback *); |
784 | extern int afs_fs_remove(struct afs_fs_cursor *, const char *, bool, u64); | 922 | extern int afs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64); |
785 | extern int afs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64); | 923 | extern int afs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64); |
786 | extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64, | 924 | extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64, |
787 | struct afs_fid *, struct afs_file_status *); | 925 | struct afs_fid *, struct afs_file_status *); |
@@ -797,7 +935,7 @@ extern int afs_fs_release_lock(struct afs_fs_cursor *); | |||
797 | extern int afs_fs_give_up_all_callbacks(struct afs_net *, struct afs_server *, | 935 | extern int afs_fs_give_up_all_callbacks(struct afs_net *, struct afs_server *, |
798 | struct afs_addr_cursor *, struct key *); | 936 | struct afs_addr_cursor *, struct key *); |
799 | extern int afs_fs_get_capabilities(struct afs_net *, struct afs_server *, | 937 | extern int afs_fs_get_capabilities(struct afs_net *, struct afs_server *, |
800 | struct afs_addr_cursor *, struct key *); | 938 | struct afs_addr_cursor *, struct key *, unsigned int, bool); |
801 | extern int afs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *, | 939 | extern int afs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *, |
802 | struct afs_fid *, struct afs_file_status *, | 940 | struct afs_fid *, struct afs_file_status *, |
803 | struct afs_callback *, unsigned int, | 941 | struct afs_callback *, unsigned int, |
@@ -807,6 +945,13 @@ extern int afs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *, | |||
807 | struct afs_callback *, struct afs_volsync *); | 945 | struct afs_callback *, struct afs_volsync *); |
808 | 946 | ||
809 | /* | 947 | /* |
948 | * fs_probe.c | ||
949 | */ | ||
950 | extern void afs_fileserver_probe_result(struct afs_call *); | ||
951 | extern int afs_probe_fileservers(struct afs_net *, struct key *, struct afs_server_list *); | ||
952 | extern int afs_wait_for_fs_probes(struct afs_server_list *, unsigned long); | ||
953 | |||
954 | /* | ||
810 | * inode.c | 955 | * inode.c |
811 | */ | 956 | */ |
812 | extern int afs_fetch_status(struct afs_vnode *, struct key *, bool); | 957 | extern int afs_fetch_status(struct afs_vnode *, struct key *, bool); |
@@ -922,7 +1067,6 @@ extern int __net_init afs_open_socket(struct afs_net *); | |||
922 | extern void __net_exit afs_close_socket(struct afs_net *); | 1067 | extern void __net_exit afs_close_socket(struct afs_net *); |
923 | extern void afs_charge_preallocation(struct work_struct *); | 1068 | extern void afs_charge_preallocation(struct work_struct *); |
924 | extern void afs_put_call(struct afs_call *); | 1069 | extern void afs_put_call(struct afs_call *); |
925 | extern int afs_queue_call_work(struct afs_call *); | ||
926 | extern long afs_make_call(struct afs_addr_cursor *, struct afs_call *, gfp_t, bool); | 1070 | extern long afs_make_call(struct afs_addr_cursor *, struct afs_call *, gfp_t, bool); |
927 | extern struct afs_call *afs_alloc_flat_call(struct afs_net *, | 1071 | extern struct afs_call *afs_alloc_flat_call(struct afs_net *, |
928 | const struct afs_call_type *, | 1072 | const struct afs_call_type *, |
@@ -930,12 +1074,39 @@ extern struct afs_call *afs_alloc_flat_call(struct afs_net *, | |||
930 | extern void afs_flat_call_destructor(struct afs_call *); | 1074 | extern void afs_flat_call_destructor(struct afs_call *); |
931 | extern void afs_send_empty_reply(struct afs_call *); | 1075 | extern void afs_send_empty_reply(struct afs_call *); |
932 | extern void afs_send_simple_reply(struct afs_call *, const void *, size_t); | 1076 | extern void afs_send_simple_reply(struct afs_call *, const void *, size_t); |
933 | extern int afs_extract_data(struct afs_call *, void *, size_t, bool); | 1077 | extern int afs_extract_data(struct afs_call *, bool); |
934 | extern int afs_protocol_error(struct afs_call *, int); | 1078 | extern int afs_protocol_error(struct afs_call *, int, enum afs_eproto_cause); |
1079 | |||
1080 | static inline void afs_extract_begin(struct afs_call *call, void *buf, size_t size) | ||
1081 | { | ||
1082 | call->kvec[0].iov_base = buf; | ||
1083 | call->kvec[0].iov_len = size; | ||
1084 | iov_iter_kvec(&call->iter, READ, call->kvec, 1, size); | ||
1085 | } | ||
1086 | |||
1087 | static inline void afs_extract_to_tmp(struct afs_call *call) | ||
1088 | { | ||
1089 | afs_extract_begin(call, &call->tmp, sizeof(call->tmp)); | ||
1090 | } | ||
1091 | |||
1092 | static inline void afs_extract_to_tmp64(struct afs_call *call) | ||
1093 | { | ||
1094 | afs_extract_begin(call, &call->tmp64, sizeof(call->tmp64)); | ||
1095 | } | ||
1096 | |||
1097 | static inline void afs_extract_discard(struct afs_call *call, size_t size) | ||
1098 | { | ||
1099 | iov_iter_discard(&call->iter, READ, size); | ||
1100 | } | ||
1101 | |||
1102 | static inline void afs_extract_to_buf(struct afs_call *call, size_t size) | ||
1103 | { | ||
1104 | afs_extract_begin(call, call->buffer, size); | ||
1105 | } | ||
935 | 1106 | ||
936 | static inline int afs_transfer_reply(struct afs_call *call) | 1107 | static inline int afs_transfer_reply(struct afs_call *call) |
937 | { | 1108 | { |
938 | return afs_extract_data(call, call->buffer, call->reply_max, false); | 1109 | return afs_extract_data(call, false); |
939 | } | 1110 | } |
940 | 1111 | ||
941 | static inline bool afs_check_call_state(struct afs_call *call, | 1112 | static inline bool afs_check_call_state(struct afs_call *call, |
@@ -1012,7 +1183,6 @@ extern void afs_put_server(struct afs_net *, struct afs_server *); | |||
1012 | extern void afs_manage_servers(struct work_struct *); | 1183 | extern void afs_manage_servers(struct work_struct *); |
1013 | extern void afs_servers_timer(struct timer_list *); | 1184 | extern void afs_servers_timer(struct timer_list *); |
1014 | extern void __net_exit afs_purge_servers(struct afs_net *); | 1185 | extern void __net_exit afs_purge_servers(struct afs_net *); |
1015 | extern bool afs_probe_fileserver(struct afs_fs_cursor *); | ||
1016 | extern bool afs_check_server_record(struct afs_fs_cursor *, struct afs_server *); | 1186 | extern bool afs_check_server_record(struct afs_fs_cursor *, struct afs_server *); |
1017 | 1187 | ||
1018 | /* | 1188 | /* |
@@ -1039,14 +1209,51 @@ extern void afs_fs_exit(void); | |||
1039 | /* | 1209 | /* |
1040 | * vlclient.c | 1210 | * vlclient.c |
1041 | */ | 1211 | */ |
1042 | extern struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_net *, | 1212 | extern struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *, |
1043 | struct afs_addr_cursor *, | 1213 | const char *, int); |
1044 | struct key *, const char *, int); | 1214 | extern struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *, const uuid_t *); |
1045 | extern struct afs_addr_list *afs_vl_get_addrs_u(struct afs_net *, struct afs_addr_cursor *, | 1215 | extern int afs_vl_get_capabilities(struct afs_net *, struct afs_addr_cursor *, struct key *, |
1046 | struct key *, const uuid_t *); | 1216 | struct afs_vlserver *, unsigned int, bool); |
1047 | extern int afs_vl_get_capabilities(struct afs_net *, struct afs_addr_cursor *, struct key *); | 1217 | extern struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *, const uuid_t *); |
1048 | extern struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_net *, struct afs_addr_cursor *, | 1218 | |
1049 | struct key *, const uuid_t *); | 1219 | /* |
1220 | * vl_probe.c | ||
1221 | */ | ||
1222 | extern void afs_vlserver_probe_result(struct afs_call *); | ||
1223 | extern int afs_send_vl_probes(struct afs_net *, struct key *, struct afs_vlserver_list *); | ||
1224 | extern int afs_wait_for_vl_probes(struct afs_vlserver_list *, unsigned long); | ||
1225 | |||
1226 | /* | ||
1227 | * vl_rotate.c | ||
1228 | */ | ||
1229 | extern bool afs_begin_vlserver_operation(struct afs_vl_cursor *, | ||
1230 | struct afs_cell *, struct key *); | ||
1231 | extern bool afs_select_vlserver(struct afs_vl_cursor *); | ||
1232 | extern bool afs_select_current_vlserver(struct afs_vl_cursor *); | ||
1233 | extern int afs_end_vlserver_operation(struct afs_vl_cursor *); | ||
1234 | |||
1235 | /* | ||
1236 | * vlserver_list.c | ||
1237 | */ | ||
1238 | static inline struct afs_vlserver *afs_get_vlserver(struct afs_vlserver *vlserver) | ||
1239 | { | ||
1240 | atomic_inc(&vlserver->usage); | ||
1241 | return vlserver; | ||
1242 | } | ||
1243 | |||
1244 | static inline struct afs_vlserver_list *afs_get_vlserverlist(struct afs_vlserver_list *vllist) | ||
1245 | { | ||
1246 | if (vllist) | ||
1247 | atomic_inc(&vllist->usage); | ||
1248 | return vllist; | ||
1249 | } | ||
1250 | |||
1251 | extern struct afs_vlserver *afs_alloc_vlserver(const char *, size_t, unsigned short); | ||
1252 | extern void afs_put_vlserver(struct afs_net *, struct afs_vlserver *); | ||
1253 | extern struct afs_vlserver_list *afs_alloc_vlserver_list(unsigned int); | ||
1254 | extern void afs_put_vlserverlist(struct afs_net *, struct afs_vlserver_list *); | ||
1255 | extern struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *, | ||
1256 | const void *, size_t); | ||
1050 | 1257 | ||
1051 | /* | 1258 | /* |
1052 | * volume.c | 1259 | * volume.c |
@@ -1089,6 +1296,36 @@ extern int afs_launder_page(struct page *); | |||
1089 | extern const struct xattr_handler *afs_xattr_handlers[]; | 1296 | extern const struct xattr_handler *afs_xattr_handlers[]; |
1090 | extern ssize_t afs_listxattr(struct dentry *, char *, size_t); | 1297 | extern ssize_t afs_listxattr(struct dentry *, char *, size_t); |
1091 | 1298 | ||
1299 | /* | ||
1300 | * yfsclient.c | ||
1301 | */ | ||
1302 | extern int yfs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool); | ||
1303 | extern int yfs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *); | ||
1304 | extern int yfs_fs_create_file(struct afs_fs_cursor *, const char *, umode_t, u64, | ||
1305 | struct afs_fid *, struct afs_file_status *, struct afs_callback *); | ||
1306 | extern int yfs_fs_make_dir(struct afs_fs_cursor *, const char *, umode_t, u64, | ||
1307 | struct afs_fid *, struct afs_file_status *, struct afs_callback *); | ||
1308 | extern int yfs_fs_remove_file2(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64); | ||
1309 | extern int yfs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64); | ||
1310 | extern int yfs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64); | ||
1311 | extern int yfs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64, | ||
1312 | struct afs_fid *, struct afs_file_status *); | ||
1313 | extern int yfs_fs_rename(struct afs_fs_cursor *, const char *, | ||
1314 | struct afs_vnode *, const char *, u64, u64); | ||
1315 | extern int yfs_fs_store_data(struct afs_fs_cursor *, struct address_space *, | ||
1316 | pgoff_t, pgoff_t, unsigned, unsigned); | ||
1317 | extern int yfs_fs_setattr(struct afs_fs_cursor *, struct iattr *); | ||
1318 | extern int yfs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *); | ||
1319 | extern int yfs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t); | ||
1320 | extern int yfs_fs_extend_lock(struct afs_fs_cursor *); | ||
1321 | extern int yfs_fs_release_lock(struct afs_fs_cursor *); | ||
1322 | extern int yfs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *, | ||
1323 | struct afs_fid *, struct afs_file_status *, | ||
1324 | struct afs_callback *, struct afs_volsync *); | ||
1325 | extern int yfs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *, | ||
1326 | struct afs_fid *, struct afs_file_status *, | ||
1327 | struct afs_callback *, unsigned int, | ||
1328 | struct afs_volsync *); | ||
1092 | 1329 | ||
1093 | /* | 1330 | /* |
1094 | * Miscellaneous inline functions. | 1331 | * Miscellaneous inline functions. |
@@ -1120,6 +1357,17 @@ static inline void afs_check_for_remote_deletion(struct afs_fs_cursor *fc, | |||
1120 | } | 1357 | } |
1121 | } | 1358 | } |
1122 | 1359 | ||
1360 | static inline int afs_io_error(struct afs_call *call, enum afs_io_error where) | ||
1361 | { | ||
1362 | trace_afs_io_error(call->debug_id, -EIO, where); | ||
1363 | return -EIO; | ||
1364 | } | ||
1365 | |||
1366 | static inline int afs_bad(struct afs_vnode *vnode, enum afs_file_error where) | ||
1367 | { | ||
1368 | trace_afs_file_error(vnode, -EIO, where); | ||
1369 | return -EIO; | ||
1370 | } | ||
1123 | 1371 | ||
1124 | /*****************************************************************************/ | 1372 | /*****************************************************************************/ |
1125 | /* | 1373 | /* |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 99fd13500a97..2e51c6994148 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -130,9 +130,10 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) | |||
130 | goto error_no_page; | 130 | goto error_no_page; |
131 | } | 131 | } |
132 | 132 | ||
133 | ret = -EIO; | 133 | if (PageError(page)) { |
134 | if (PageError(page)) | 134 | ret = afs_bad(AFS_FS_I(d_inode(mntpt)), afs_file_error_mntpt); |
135 | goto error; | 135 | goto error; |
136 | } | ||
136 | 137 | ||
137 | buf = kmap_atomic(page); | 138 | buf = kmap_atomic(page); |
138 | memcpy(devname, buf, size); | 139 | memcpy(devname, buf, size); |
diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 9101f62707af..be2ee3bbd0a9 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c | |||
@@ -17,6 +17,11 @@ | |||
17 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
18 | #include "internal.h" | 18 | #include "internal.h" |
19 | 19 | ||
20 | struct afs_vl_seq_net_private { | ||
21 | struct seq_net_private seq; /* Must be first */ | ||
22 | struct afs_vlserver_list *vllist; | ||
23 | }; | ||
24 | |||
20 | static inline struct afs_net *afs_seq2net(struct seq_file *m) | 25 | static inline struct afs_net *afs_seq2net(struct seq_file *m) |
21 | { | 26 | { |
22 | return afs_net(seq_file_net(m)); | 27 | return afs_net(seq_file_net(m)); |
@@ -32,16 +37,24 @@ static inline struct afs_net *afs_seq2net_single(struct seq_file *m) | |||
32 | */ | 37 | */ |
33 | static int afs_proc_cells_show(struct seq_file *m, void *v) | 38 | static int afs_proc_cells_show(struct seq_file *m, void *v) |
34 | { | 39 | { |
35 | struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link); | 40 | struct afs_vlserver_list *vllist; |
41 | struct afs_cell *cell; | ||
36 | 42 | ||
37 | if (v == SEQ_START_TOKEN) { | 43 | if (v == SEQ_START_TOKEN) { |
38 | /* display header on line 1 */ | 44 | /* display header on line 1 */ |
39 | seq_puts(m, "USE NAME\n"); | 45 | seq_puts(m, "USE TTL SV NAME\n"); |
40 | return 0; | 46 | return 0; |
41 | } | 47 | } |
42 | 48 | ||
49 | cell = list_entry(v, struct afs_cell, proc_link); | ||
50 | vllist = rcu_dereference(cell->vl_servers); | ||
51 | |||
43 | /* display one cell per line on subsequent lines */ | 52 | /* display one cell per line on subsequent lines */ |
44 | seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name); | 53 | seq_printf(m, "%3u %6lld %2u %s\n", |
54 | atomic_read(&cell->usage), | ||
55 | cell->dns_expiry - ktime_get_real_seconds(), | ||
56 | vllist ? vllist->nr_servers : 0, | ||
57 | cell->name); | ||
45 | return 0; | 58 | return 0; |
46 | } | 59 | } |
47 | 60 | ||
@@ -208,7 +221,7 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v) | |||
208 | return 0; | 221 | return 0; |
209 | } | 222 | } |
210 | 223 | ||
211 | seq_printf(m, "%3d %08x %s\n", | 224 | seq_printf(m, "%3d %08llx %s\n", |
212 | atomic_read(&vol->usage), vol->vid, | 225 | atomic_read(&vol->usage), vol->vid, |
213 | afs_vol_types[vol->type]); | 226 | afs_vol_types[vol->type]); |
214 | 227 | ||
@@ -247,61 +260,102 @@ static const struct seq_operations afs_proc_cell_volumes_ops = { | |||
247 | .show = afs_proc_cell_volumes_show, | 260 | .show = afs_proc_cell_volumes_show, |
248 | }; | 261 | }; |
249 | 262 | ||
263 | static const char *const dns_record_sources[NR__dns_record_source + 1] = { | ||
264 | [DNS_RECORD_UNAVAILABLE] = "unav", | ||
265 | [DNS_RECORD_FROM_CONFIG] = "cfg", | ||
266 | [DNS_RECORD_FROM_DNS_A] = "A", | ||
267 | [DNS_RECORD_FROM_DNS_AFSDB] = "AFSDB", | ||
268 | [DNS_RECORD_FROM_DNS_SRV] = "SRV", | ||
269 | [DNS_RECORD_FROM_NSS] = "nss", | ||
270 | [NR__dns_record_source] = "[weird]" | ||
271 | }; | ||
272 | |||
273 | static const char *const dns_lookup_statuses[NR__dns_lookup_status + 1] = { | ||
274 | [DNS_LOOKUP_NOT_DONE] = "no-lookup", | ||
275 | [DNS_LOOKUP_GOOD] = "good", | ||
276 | [DNS_LOOKUP_GOOD_WITH_BAD] = "good/bad", | ||
277 | [DNS_LOOKUP_BAD] = "bad", | ||
278 | [DNS_LOOKUP_GOT_NOT_FOUND] = "not-found", | ||
279 | [DNS_LOOKUP_GOT_LOCAL_FAILURE] = "local-failure", | ||
280 | [DNS_LOOKUP_GOT_TEMP_FAILURE] = "temp-failure", | ||
281 | [DNS_LOOKUP_GOT_NS_FAILURE] = "ns-failure", | ||
282 | [NR__dns_lookup_status] = "[weird]" | ||
283 | }; | ||
284 | |||
250 | /* | 285 | /* |
251 | * Display the list of Volume Location servers we're using for a cell. | 286 | * Display the list of Volume Location servers we're using for a cell. |
252 | */ | 287 | */ |
253 | static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v) | 288 | static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v) |
254 | { | 289 | { |
255 | struct sockaddr_rxrpc *addr = v; | 290 | const struct afs_vl_seq_net_private *priv = m->private; |
291 | const struct afs_vlserver_list *vllist = priv->vllist; | ||
292 | const struct afs_vlserver_entry *entry; | ||
293 | const struct afs_vlserver *vlserver; | ||
294 | const struct afs_addr_list *alist; | ||
295 | int i; | ||
256 | 296 | ||
257 | /* display header on line 1 */ | 297 | if (v == SEQ_START_TOKEN) { |
258 | if (v == (void *)1) { | 298 | seq_printf(m, "# source %s, status %s\n", |
259 | seq_puts(m, "ADDRESS\n"); | 299 | dns_record_sources[vllist->source], |
300 | dns_lookup_statuses[vllist->status]); | ||
260 | return 0; | 301 | return 0; |
261 | } | 302 | } |
262 | 303 | ||
263 | /* display one cell per line on subsequent lines */ | 304 | entry = v; |
264 | seq_printf(m, "%pISp\n", &addr->transport); | 305 | vlserver = entry->server; |
306 | alist = rcu_dereference(vlserver->addresses); | ||
307 | |||
308 | seq_printf(m, "%s [p=%hu w=%hu s=%s,%s]:\n", | ||
309 | vlserver->name, entry->priority, entry->weight, | ||
310 | dns_record_sources[alist ? alist->source : entry->source], | ||
311 | dns_lookup_statuses[alist ? alist->status : entry->status]); | ||
312 | if (alist) { | ||
313 | for (i = 0; i < alist->nr_addrs; i++) | ||
314 | seq_printf(m, " %c %pISpc\n", | ||
315 | alist->preferred == i ? '>' : '-', | ||
316 | &alist->addrs[i].transport); | ||
317 | } | ||
265 | return 0; | 318 | return 0; |
266 | } | 319 | } |
267 | 320 | ||
268 | static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos) | 321 | static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos) |
269 | __acquires(rcu) | 322 | __acquires(rcu) |
270 | { | 323 | { |
271 | struct afs_addr_list *alist; | 324 | struct afs_vl_seq_net_private *priv = m->private; |
325 | struct afs_vlserver_list *vllist; | ||
272 | struct afs_cell *cell = PDE_DATA(file_inode(m->file)); | 326 | struct afs_cell *cell = PDE_DATA(file_inode(m->file)); |
273 | loff_t pos = *_pos; | 327 | loff_t pos = *_pos; |
274 | 328 | ||
275 | rcu_read_lock(); | 329 | rcu_read_lock(); |
276 | 330 | ||
277 | alist = rcu_dereference(cell->vl_addrs); | 331 | vllist = rcu_dereference(cell->vl_servers); |
332 | priv->vllist = vllist; | ||
278 | 333 | ||
279 | /* allow for the header line */ | 334 | if (pos < 0) |
280 | if (!pos) | 335 | *_pos = pos = 0; |
281 | return (void *) 1; | 336 | if (pos == 0) |
282 | pos--; | 337 | return SEQ_START_TOKEN; |
283 | 338 | ||
284 | if (!alist || pos >= alist->nr_addrs) | 339 | if (!vllist || pos - 1 >= vllist->nr_servers) |
285 | return NULL; | 340 | return NULL; |
286 | 341 | ||
287 | return alist->addrs + pos; | 342 | return &vllist->servers[pos - 1]; |
288 | } | 343 | } |
289 | 344 | ||
290 | static void *afs_proc_cell_vlservers_next(struct seq_file *m, void *v, | 345 | static void *afs_proc_cell_vlservers_next(struct seq_file *m, void *v, |
291 | loff_t *_pos) | 346 | loff_t *_pos) |
292 | { | 347 | { |
293 | struct afs_addr_list *alist; | 348 | struct afs_vl_seq_net_private *priv = m->private; |
294 | struct afs_cell *cell = PDE_DATA(file_inode(m->file)); | 349 | struct afs_vlserver_list *vllist = priv->vllist; |
295 | loff_t pos; | 350 | loff_t pos; |
296 | 351 | ||
297 | alist = rcu_dereference(cell->vl_addrs); | ||
298 | |||
299 | pos = *_pos; | 352 | pos = *_pos; |
300 | (*_pos)++; | 353 | pos++; |
301 | if (!alist || pos >= alist->nr_addrs) | 354 | *_pos = pos; |
355 | if (!vllist || pos - 1 >= vllist->nr_servers) | ||
302 | return NULL; | 356 | return NULL; |
303 | 357 | ||
304 | return alist->addrs + pos; | 358 | return &vllist->servers[pos - 1]; |
305 | } | 359 | } |
306 | 360 | ||
307 | static void afs_proc_cell_vlservers_stop(struct seq_file *m, void *v) | 361 | static void afs_proc_cell_vlservers_stop(struct seq_file *m, void *v) |
@@ -337,11 +391,11 @@ static int afs_proc_servers_show(struct seq_file *m, void *v) | |||
337 | &server->uuid, | 391 | &server->uuid, |
338 | atomic_read(&server->usage), | 392 | atomic_read(&server->usage), |
339 | &alist->addrs[0].transport, | 393 | &alist->addrs[0].transport, |
340 | alist->index == 0 ? "*" : ""); | 394 | alist->preferred == 0 ? "*" : ""); |
341 | for (i = 1; i < alist->nr_addrs; i++) | 395 | for (i = 1; i < alist->nr_addrs; i++) |
342 | seq_printf(m, " %pISpc%s\n", | 396 | seq_printf(m, " %pISpc%s\n", |
343 | &alist->addrs[i].transport, | 397 | &alist->addrs[i].transport, |
344 | alist->index == i ? "*" : ""); | 398 | alist->preferred == i ? "*" : ""); |
345 | return 0; | 399 | return 0; |
346 | } | 400 | } |
347 | 401 | ||
@@ -562,7 +616,7 @@ int afs_proc_cell_setup(struct afs_cell *cell) | |||
562 | 616 | ||
563 | if (!proc_create_net_data("vlservers", 0444, dir, | 617 | if (!proc_create_net_data("vlservers", 0444, dir, |
564 | &afs_proc_cell_vlservers_ops, | 618 | &afs_proc_cell_vlservers_ops, |
565 | sizeof(struct seq_net_private), | 619 | sizeof(struct afs_vl_seq_net_private), |
566 | cell) || | 620 | cell) || |
567 | !proc_create_net_data("volumes", 0444, dir, | 621 | !proc_create_net_data("volumes", 0444, dir, |
568 | &afs_proc_cell_volumes_ops, | 622 | &afs_proc_cell_volumes_ops, |
diff --git a/fs/afs/protocol_yfs.h b/fs/afs/protocol_yfs.h new file mode 100644 index 000000000000..07bc10f076aa --- /dev/null +++ b/fs/afs/protocol_yfs.h | |||
@@ -0,0 +1,163 @@ | |||
1 | /* YFS protocol bits | ||
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 | #define YFS_FS_SERVICE 2500 | ||
13 | #define YFS_CM_SERVICE 2501 | ||
14 | |||
15 | #define YFSCBMAX 1024 | ||
16 | |||
17 | enum YFS_CM_Operations { | ||
18 | YFSCBProbe = 206, /* probe client */ | ||
19 | YFSCBGetLock = 207, /* get contents of CM lock table */ | ||
20 | YFSCBXStatsVersion = 209, /* get version of extended statistics */ | ||
21 | YFSCBGetXStats = 210, /* get contents of extended statistics data */ | ||
22 | YFSCBInitCallBackState3 = 213, /* initialise callback state, version 3 */ | ||
23 | YFSCBProbeUuid = 214, /* check the client hasn't rebooted */ | ||
24 | YFSCBGetServerPrefs = 215, | ||
25 | YFSCBGetCellServDV = 216, | ||
26 | YFSCBGetLocalCell = 217, | ||
27 | YFSCBGetCacheConfig = 218, | ||
28 | YFSCBGetCellByNum = 65537, | ||
29 | YFSCBTellMeAboutYourself = 65538, /* get client capabilities */ | ||
30 | YFSCBCallBack = 64204, | ||
31 | }; | ||
32 | |||
33 | enum YFS_FS_Operations { | ||
34 | YFSFETCHACL = 64131, /* YFS Fetch file ACL */ | ||
35 | YFSFETCHSTATUS = 64132, /* YFS Fetch file status */ | ||
36 | YFSSTOREACL = 64134, /* YFS Store file ACL */ | ||
37 | YFSSTORESTATUS = 64135, /* YFS Store file status */ | ||
38 | YFSREMOVEFILE = 64136, /* YFS Remove a file */ | ||
39 | YFSCREATEFILE = 64137, /* YFS Create a file */ | ||
40 | YFSRENAME = 64138, /* YFS Rename or move a file or directory */ | ||
41 | YFSSYMLINK = 64139, /* YFS Create a symbolic link */ | ||
42 | YFSLINK = 64140, /* YFS Create a hard link */ | ||
43 | YFSMAKEDIR = 64141, /* YFS Create a directory */ | ||
44 | YFSREMOVEDIR = 64142, /* YFS Remove a directory */ | ||
45 | YFSGETVOLUMESTATUS = 64149, /* YFS Get volume status information */ | ||
46 | YFSSETVOLUMESTATUS = 64150, /* YFS Set volume status information */ | ||
47 | YFSSETLOCK = 64156, /* YFS Request a file lock */ | ||
48 | YFSEXTENDLOCK = 64157, /* YFS Extend a file lock */ | ||
49 | YFSRELEASELOCK = 64158, /* YFS Release a file lock */ | ||
50 | YFSLOOKUP = 64161, /* YFS lookup file in directory */ | ||
51 | YFSFLUSHCPS = 64165, | ||
52 | YFSFETCHOPAQUEACL = 64168, | ||
53 | YFSWHOAMI = 64170, | ||
54 | YFSREMOVEACL = 64171, | ||
55 | YFSREMOVEFILE2 = 64173, | ||
56 | YFSSTOREOPAQUEACL2 = 64174, | ||
57 | YFSINLINEBULKSTATUS = 64536, /* YFS Fetch multiple file statuses with errors */ | ||
58 | YFSFETCHDATA64 = 64537, /* YFS Fetch file data */ | ||
59 | YFSSTOREDATA64 = 64538, /* YFS Store file data */ | ||
60 | YFSUPDATESYMLINK = 64540, | ||
61 | }; | ||
62 | |||
63 | struct yfs_xdr_u64 { | ||
64 | __be32 msw; | ||
65 | __be32 lsw; | ||
66 | } __packed; | ||
67 | |||
68 | static inline u64 xdr_to_u64(const struct yfs_xdr_u64 x) | ||
69 | { | ||
70 | return ((u64)ntohl(x.msw) << 32) | ntohl(x.lsw); | ||
71 | } | ||
72 | |||
73 | static inline struct yfs_xdr_u64 u64_to_xdr(const u64 x) | ||
74 | { | ||
75 | return (struct yfs_xdr_u64){ .msw = htonl(x >> 32), .lsw = htonl(x) }; | ||
76 | } | ||
77 | |||
78 | struct yfs_xdr_vnode { | ||
79 | struct yfs_xdr_u64 lo; | ||
80 | __be32 hi; | ||
81 | __be32 unique; | ||
82 | } __packed; | ||
83 | |||
84 | struct yfs_xdr_YFSFid { | ||
85 | struct yfs_xdr_u64 volume; | ||
86 | struct yfs_xdr_vnode vnode; | ||
87 | } __packed; | ||
88 | |||
89 | |||
90 | struct yfs_xdr_YFSFetchStatus { | ||
91 | __be32 type; | ||
92 | __be32 nlink; | ||
93 | struct yfs_xdr_u64 size; | ||
94 | struct yfs_xdr_u64 data_version; | ||
95 | struct yfs_xdr_u64 author; | ||
96 | struct yfs_xdr_u64 owner; | ||
97 | struct yfs_xdr_u64 group; | ||
98 | __be32 mode; | ||
99 | __be32 caller_access; | ||
100 | __be32 anon_access; | ||
101 | struct yfs_xdr_vnode parent; | ||
102 | __be32 data_access_protocol; | ||
103 | struct yfs_xdr_u64 mtime_client; | ||
104 | struct yfs_xdr_u64 mtime_server; | ||
105 | __be32 lock_count; | ||
106 | __be32 abort_code; | ||
107 | } __packed; | ||
108 | |||
109 | struct yfs_xdr_YFSCallBack { | ||
110 | __be32 version; | ||
111 | struct yfs_xdr_u64 expiration_time; | ||
112 | __be32 type; | ||
113 | } __packed; | ||
114 | |||
115 | struct yfs_xdr_YFSStoreStatus { | ||
116 | __be32 mask; | ||
117 | __be32 mode; | ||
118 | struct yfs_xdr_u64 mtime_client; | ||
119 | struct yfs_xdr_u64 owner; | ||
120 | struct yfs_xdr_u64 group; | ||
121 | } __packed; | ||
122 | |||
123 | struct yfs_xdr_RPCFlags { | ||
124 | __be32 rpc_flags; | ||
125 | } __packed; | ||
126 | |||
127 | struct yfs_xdr_YFSVolSync { | ||
128 | struct yfs_xdr_u64 vol_creation_date; | ||
129 | struct yfs_xdr_u64 vol_update_date; | ||
130 | struct yfs_xdr_u64 max_quota; | ||
131 | struct yfs_xdr_u64 blocks_in_use; | ||
132 | struct yfs_xdr_u64 blocks_avail; | ||
133 | } __packed; | ||
134 | |||
135 | enum yfs_volume_type { | ||
136 | yfs_volume_type_ro = 0, | ||
137 | yfs_volume_type_rw = 1, | ||
138 | }; | ||
139 | |||
140 | #define yfs_FVSOnline 0x1 | ||
141 | #define yfs_FVSInservice 0x2 | ||
142 | #define yfs_FVSBlessed 0x4 | ||
143 | #define yfs_FVSNeedsSalvage 0x8 | ||
144 | |||
145 | struct yfs_xdr_YFSFetchVolumeStatus { | ||
146 | struct yfs_xdr_u64 vid; | ||
147 | struct yfs_xdr_u64 parent_id; | ||
148 | __be32 flags; | ||
149 | __be32 type; | ||
150 | struct yfs_xdr_u64 max_quota; | ||
151 | struct yfs_xdr_u64 blocks_in_use; | ||
152 | struct yfs_xdr_u64 part_blocks_avail; | ||
153 | struct yfs_xdr_u64 part_max_blocks; | ||
154 | struct yfs_xdr_u64 vol_copy_date; | ||
155 | struct yfs_xdr_u64 vol_backup_date; | ||
156 | } __packed; | ||
157 | |||
158 | struct yfs_xdr_YFSStoreVolumeStatus { | ||
159 | __be32 mask; | ||
160 | struct yfs_xdr_u64 min_quota; | ||
161 | struct yfs_xdr_u64 max_quota; | ||
162 | struct yfs_xdr_u64 file_quota; | ||
163 | } __packed; | ||
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index 1faef56b12bd..00504254c1c2 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c | |||
@@ -19,14 +19,6 @@ | |||
19 | #include "afs_fs.h" | 19 | #include "afs_fs.h" |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * Initialise a filesystem server cursor for iterating over FS servers. | ||
23 | */ | ||
24 | static void afs_init_fs_cursor(struct afs_fs_cursor *fc, struct afs_vnode *vnode) | ||
25 | { | ||
26 | memset(fc, 0, sizeof(*fc)); | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Begin an operation on the fileserver. | 22 | * Begin an operation on the fileserver. |
31 | * | 23 | * |
32 | * Fileserver operations are serialised on the server by vnode, so we serialise | 24 | * Fileserver operations are serialised on the server by vnode, so we serialise |
@@ -35,13 +27,14 @@ static void afs_init_fs_cursor(struct afs_fs_cursor *fc, struct afs_vnode *vnode | |||
35 | bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | 27 | bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode, |
36 | struct key *key) | 28 | struct key *key) |
37 | { | 29 | { |
38 | afs_init_fs_cursor(fc, vnode); | 30 | memset(fc, 0, sizeof(*fc)); |
39 | fc->vnode = vnode; | 31 | fc->vnode = vnode; |
40 | fc->key = key; | 32 | fc->key = key; |
41 | fc->ac.error = SHRT_MAX; | 33 | fc->ac.error = SHRT_MAX; |
34 | fc->error = -EDESTADDRREQ; | ||
42 | 35 | ||
43 | if (mutex_lock_interruptible(&vnode->io_lock) < 0) { | 36 | if (mutex_lock_interruptible(&vnode->io_lock) < 0) { |
44 | fc->ac.error = -EINTR; | 37 | fc->error = -EINTR; |
45 | fc->flags |= AFS_FS_CURSOR_STOP; | 38 | fc->flags |= AFS_FS_CURSOR_STOP; |
46 | return false; | 39 | return false; |
47 | } | 40 | } |
@@ -65,12 +58,15 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc, | |||
65 | fc->server_list = afs_get_serverlist(vnode->volume->servers); | 58 | fc->server_list = afs_get_serverlist(vnode->volume->servers); |
66 | read_unlock(&vnode->volume->servers_lock); | 59 | read_unlock(&vnode->volume->servers_lock); |
67 | 60 | ||
61 | fc->untried = (1UL << fc->server_list->nr_servers) - 1; | ||
62 | fc->index = READ_ONCE(fc->server_list->preferred); | ||
63 | |||
68 | cbi = vnode->cb_interest; | 64 | cbi = vnode->cb_interest; |
69 | if (cbi) { | 65 | if (cbi) { |
70 | /* See if the vnode's preferred record is still available */ | 66 | /* See if the vnode's preferred record is still available */ |
71 | for (i = 0; i < fc->server_list->nr_servers; i++) { | 67 | for (i = 0; i < fc->server_list->nr_servers; i++) { |
72 | if (fc->server_list->servers[i].cb_interest == cbi) { | 68 | if (fc->server_list->servers[i].cb_interest == cbi) { |
73 | fc->start = i; | 69 | fc->index = i; |
74 | goto found_interest; | 70 | goto found_interest; |
75 | } | 71 | } |
76 | } | 72 | } |
@@ -80,7 +76,7 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc, | |||
80 | * and have to return an error. | 76 | * and have to return an error. |
81 | */ | 77 | */ |
82 | if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) { | 78 | if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) { |
83 | fc->ac.error = -ESTALE; | 79 | fc->error = -ESTALE; |
84 | return false; | 80 | return false; |
85 | } | 81 | } |
86 | 82 | ||
@@ -94,12 +90,9 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc, | |||
94 | 90 | ||
95 | afs_put_cb_interest(afs_v2net(vnode), cbi); | 91 | afs_put_cb_interest(afs_v2net(vnode), cbi); |
96 | cbi = NULL; | 92 | cbi = NULL; |
97 | } else { | ||
98 | fc->start = READ_ONCE(fc->server_list->index); | ||
99 | } | 93 | } |
100 | 94 | ||
101 | found_interest: | 95 | found_interest: |
102 | fc->index = fc->start; | ||
103 | return true; | 96 | return true; |
104 | } | 97 | } |
105 | 98 | ||
@@ -117,7 +110,7 @@ static void afs_busy(struct afs_volume *volume, u32 abort_code) | |||
117 | default: m = "busy"; break; | 110 | default: m = "busy"; break; |
118 | } | 111 | } |
119 | 112 | ||
120 | pr_notice("kAFS: Volume %u '%s' is %s\n", volume->vid, volume->name, m); | 113 | pr_notice("kAFS: Volume %llu '%s' is %s\n", volume->vid, volume->name, m); |
121 | } | 114 | } |
122 | 115 | ||
123 | /* | 116 | /* |
@@ -127,7 +120,7 @@ static bool afs_sleep_and_retry(struct afs_fs_cursor *fc) | |||
127 | { | 120 | { |
128 | msleep_interruptible(1000); | 121 | msleep_interruptible(1000); |
129 | if (signal_pending(current)) { | 122 | if (signal_pending(current)) { |
130 | fc->ac.error = -ERESTARTSYS; | 123 | fc->error = -ERESTARTSYS; |
131 | return false; | 124 | return false; |
132 | } | 125 | } |
133 | 126 | ||
@@ -143,27 +136,32 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
143 | struct afs_addr_list *alist; | 136 | struct afs_addr_list *alist; |
144 | struct afs_server *server; | 137 | struct afs_server *server; |
145 | struct afs_vnode *vnode = fc->vnode; | 138 | struct afs_vnode *vnode = fc->vnode; |
139 | u32 rtt, abort_code; | ||
140 | int error = fc->ac.error, i; | ||
146 | 141 | ||
147 | _enter("%u/%u,%u/%u,%d,%d", | 142 | _enter("%lx[%d],%lx[%d],%d,%d", |
148 | fc->index, fc->start, | 143 | fc->untried, fc->index, |
149 | fc->ac.index, fc->ac.start, | 144 | fc->ac.tried, fc->ac.index, |
150 | fc->ac.error, fc->ac.abort_code); | 145 | error, fc->ac.abort_code); |
151 | 146 | ||
152 | if (fc->flags & AFS_FS_CURSOR_STOP) { | 147 | if (fc->flags & AFS_FS_CURSOR_STOP) { |
153 | _leave(" = f [stopped]"); | 148 | _leave(" = f [stopped]"); |
154 | return false; | 149 | return false; |
155 | } | 150 | } |
156 | 151 | ||
152 | fc->nr_iterations++; | ||
153 | |||
157 | /* Evaluate the result of the previous operation, if there was one. */ | 154 | /* Evaluate the result of the previous operation, if there was one. */ |
158 | switch (fc->ac.error) { | 155 | switch (error) { |
159 | case SHRT_MAX: | 156 | case SHRT_MAX: |
160 | goto start; | 157 | goto start; |
161 | 158 | ||
162 | case 0: | 159 | case 0: |
163 | default: | 160 | default: |
164 | /* Success or local failure. Stop. */ | 161 | /* Success or local failure. Stop. */ |
162 | fc->error = error; | ||
165 | fc->flags |= AFS_FS_CURSOR_STOP; | 163 | fc->flags |= AFS_FS_CURSOR_STOP; |
166 | _leave(" = f [okay/local %d]", fc->ac.error); | 164 | _leave(" = f [okay/local %d]", error); |
167 | return false; | 165 | return false; |
168 | 166 | ||
169 | case -ECONNABORTED: | 167 | case -ECONNABORTED: |
@@ -178,7 +176,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
178 | * - May indicate that the fileserver couldn't attach to the vol. | 176 | * - May indicate that the fileserver couldn't attach to the vol. |
179 | */ | 177 | */ |
180 | if (fc->flags & AFS_FS_CURSOR_VNOVOL) { | 178 | if (fc->flags & AFS_FS_CURSOR_VNOVOL) { |
181 | fc->ac.error = -EREMOTEIO; | 179 | fc->error = -EREMOTEIO; |
182 | goto next_server; | 180 | goto next_server; |
183 | } | 181 | } |
184 | 182 | ||
@@ -187,12 +185,12 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
187 | write_unlock(&vnode->volume->servers_lock); | 185 | write_unlock(&vnode->volume->servers_lock); |
188 | 186 | ||
189 | set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags); | 187 | set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags); |
190 | fc->ac.error = afs_check_volume_status(vnode->volume, fc->key); | 188 | error = afs_check_volume_status(vnode->volume, fc->key); |
191 | if (fc->ac.error < 0) | 189 | if (error < 0) |
192 | goto failed; | 190 | goto failed_set_error; |
193 | 191 | ||
194 | if (test_bit(AFS_VOLUME_DELETED, &vnode->volume->flags)) { | 192 | if (test_bit(AFS_VOLUME_DELETED, &vnode->volume->flags)) { |
195 | fc->ac.error = -ENOMEDIUM; | 193 | fc->error = -ENOMEDIUM; |
196 | goto failed; | 194 | goto failed; |
197 | } | 195 | } |
198 | 196 | ||
@@ -200,7 +198,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
200 | * it's the fileserver having trouble. | 198 | * it's the fileserver having trouble. |
201 | */ | 199 | */ |
202 | if (vnode->volume->servers == fc->server_list) { | 200 | if (vnode->volume->servers == fc->server_list) { |
203 | fc->ac.error = -EREMOTEIO; | 201 | fc->error = -EREMOTEIO; |
204 | goto next_server; | 202 | goto next_server; |
205 | } | 203 | } |
206 | 204 | ||
@@ -215,7 +213,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
215 | case VONLINE: | 213 | case VONLINE: |
216 | case VDISKFULL: | 214 | case VDISKFULL: |
217 | case VOVERQUOTA: | 215 | case VOVERQUOTA: |
218 | fc->ac.error = afs_abort_to_error(fc->ac.abort_code); | 216 | fc->error = afs_abort_to_error(fc->ac.abort_code); |
219 | goto next_server; | 217 | goto next_server; |
220 | 218 | ||
221 | case VOFFLINE: | 219 | case VOFFLINE: |
@@ -224,11 +222,11 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
224 | clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags); | 222 | clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags); |
225 | } | 223 | } |
226 | if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) { | 224 | if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) { |
227 | fc->ac.error = -EADV; | 225 | fc->error = -EADV; |
228 | goto failed; | 226 | goto failed; |
229 | } | 227 | } |
230 | if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) { | 228 | if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) { |
231 | fc->ac.error = -ESTALE; | 229 | fc->error = -ESTALE; |
232 | goto failed; | 230 | goto failed; |
233 | } | 231 | } |
234 | goto busy; | 232 | goto busy; |
@@ -240,7 +238,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
240 | * have a file lock we need to maintain. | 238 | * have a file lock we need to maintain. |
241 | */ | 239 | */ |
242 | if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) { | 240 | if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) { |
243 | fc->ac.error = -EBUSY; | 241 | fc->error = -EBUSY; |
244 | goto failed; | 242 | goto failed; |
245 | } | 243 | } |
246 | if (!test_and_set_bit(AFS_VOLUME_BUSY, &vnode->volume->flags)) { | 244 | if (!test_and_set_bit(AFS_VOLUME_BUSY, &vnode->volume->flags)) { |
@@ -269,16 +267,16 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
269 | * honour, just in case someone sets up a loop. | 267 | * honour, just in case someone sets up a loop. |
270 | */ | 268 | */ |
271 | if (fc->flags & AFS_FS_CURSOR_VMOVED) { | 269 | if (fc->flags & AFS_FS_CURSOR_VMOVED) { |
272 | fc->ac.error = -EREMOTEIO; | 270 | fc->error = -EREMOTEIO; |
273 | goto failed; | 271 | goto failed; |
274 | } | 272 | } |
275 | fc->flags |= AFS_FS_CURSOR_VMOVED; | 273 | fc->flags |= AFS_FS_CURSOR_VMOVED; |
276 | 274 | ||
277 | set_bit(AFS_VOLUME_WAIT, &vnode->volume->flags); | 275 | set_bit(AFS_VOLUME_WAIT, &vnode->volume->flags); |
278 | set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags); | 276 | set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags); |
279 | fc->ac.error = afs_check_volume_status(vnode->volume, fc->key); | 277 | error = afs_check_volume_status(vnode->volume, fc->key); |
280 | if (fc->ac.error < 0) | 278 | if (error < 0) |
281 | goto failed; | 279 | goto failed_set_error; |
282 | 280 | ||
283 | /* If the server list didn't change, then the VLDB is | 281 | /* If the server list didn't change, then the VLDB is |
284 | * out of sync with the fileservers. This is hopefully | 282 | * out of sync with the fileservers. This is hopefully |
@@ -290,7 +288,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
290 | * TODO: Retry a few times with sleeps. | 288 | * TODO: Retry a few times with sleeps. |
291 | */ | 289 | */ |
292 | if (vnode->volume->servers == fc->server_list) { | 290 | if (vnode->volume->servers == fc->server_list) { |
293 | fc->ac.error = -ENOMEDIUM; | 291 | fc->error = -ENOMEDIUM; |
294 | goto failed; | 292 | goto failed; |
295 | } | 293 | } |
296 | 294 | ||
@@ -299,20 +297,25 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
299 | default: | 297 | default: |
300 | clear_bit(AFS_VOLUME_OFFLINE, &vnode->volume->flags); | 298 | clear_bit(AFS_VOLUME_OFFLINE, &vnode->volume->flags); |
301 | clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags); | 299 | clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags); |
302 | fc->ac.error = afs_abort_to_error(fc->ac.abort_code); | 300 | fc->error = afs_abort_to_error(fc->ac.abort_code); |
303 | goto failed; | 301 | goto failed; |
304 | } | 302 | } |
305 | 303 | ||
304 | case -ETIMEDOUT: | ||
305 | case -ETIME: | ||
306 | if (fc->error != -EDESTADDRREQ) | ||
307 | goto iterate_address; | ||
308 | /* Fall through */ | ||
306 | case -ENETUNREACH: | 309 | case -ENETUNREACH: |
307 | case -EHOSTUNREACH: | 310 | case -EHOSTUNREACH: |
308 | case -ECONNREFUSED: | 311 | case -ECONNREFUSED: |
309 | case -ETIMEDOUT: | ||
310 | case -ETIME: | ||
311 | _debug("no conn"); | 312 | _debug("no conn"); |
313 | fc->error = error; | ||
312 | goto iterate_address; | 314 | goto iterate_address; |
313 | 315 | ||
314 | case -ECONNRESET: | 316 | case -ECONNRESET: |
315 | _debug("call reset"); | 317 | _debug("call reset"); |
318 | fc->error = error; | ||
316 | goto failed; | 319 | goto failed; |
317 | } | 320 | } |
318 | 321 | ||
@@ -328,15 +331,57 @@ start: | |||
328 | /* See if we need to do an update of the volume record. Note that the | 331 | /* See if we need to do an update of the volume record. Note that the |
329 | * volume may have moved or even have been deleted. | 332 | * volume may have moved or even have been deleted. |
330 | */ | 333 | */ |
331 | fc->ac.error = afs_check_volume_status(vnode->volume, fc->key); | 334 | error = afs_check_volume_status(vnode->volume, fc->key); |
332 | if (fc->ac.error < 0) | 335 | if (error < 0) |
333 | goto failed; | 336 | goto failed_set_error; |
334 | 337 | ||
335 | if (!afs_start_fs_iteration(fc, vnode)) | 338 | if (!afs_start_fs_iteration(fc, vnode)) |
336 | goto failed; | 339 | goto failed; |
337 | 340 | ||
338 | use_server: | 341 | _debug("__ VOL %llx __", vnode->volume->vid); |
339 | _debug("use"); | 342 | error = afs_probe_fileservers(afs_v2net(vnode), fc->key, fc->server_list); |
343 | if (error < 0) | ||
344 | goto failed_set_error; | ||
345 | |||
346 | pick_server: | ||
347 | _debug("pick [%lx]", fc->untried); | ||
348 | |||
349 | error = afs_wait_for_fs_probes(fc->server_list, fc->untried); | ||
350 | if (error < 0) | ||
351 | goto failed_set_error; | ||
352 | |||
353 | /* Pick the untried server with the lowest RTT. If we have outstanding | ||
354 | * callbacks, we stick with the server we're already using if we can. | ||
355 | */ | ||
356 | if (fc->cbi) { | ||
357 | _debug("cbi %u", fc->index); | ||
358 | if (test_bit(fc->index, &fc->untried)) | ||
359 | goto selected_server; | ||
360 | afs_put_cb_interest(afs_v2net(vnode), fc->cbi); | ||
361 | fc->cbi = NULL; | ||
362 | _debug("nocbi"); | ||
363 | } | ||
364 | |||
365 | fc->index = -1; | ||
366 | rtt = U32_MAX; | ||
367 | for (i = 0; i < fc->server_list->nr_servers; i++) { | ||
368 | struct afs_server *s = fc->server_list->servers[i].server; | ||
369 | |||
370 | if (!test_bit(i, &fc->untried) || !s->probe.responded) | ||
371 | continue; | ||
372 | if (s->probe.rtt < rtt) { | ||
373 | fc->index = i; | ||
374 | rtt = s->probe.rtt; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | if (fc->index == -1) | ||
379 | goto no_more_servers; | ||
380 | |||
381 | selected_server: | ||
382 | _debug("use %d", fc->index); | ||
383 | __clear_bit(fc->index, &fc->untried); | ||
384 | |||
340 | /* We're starting on a different fileserver from the list. We need to | 385 | /* We're starting on a different fileserver from the list. We need to |
341 | * check it, create a callback intercept, find its address list and | 386 | * check it, create a callback intercept, find its address list and |
342 | * probe its capabilities before we use it. | 387 | * probe its capabilities before we use it. |
@@ -354,10 +399,10 @@ use_server: | |||
354 | * break request before we've finished decoding the reply and | 399 | * break request before we've finished decoding the reply and |
355 | * installing the vnode. | 400 | * installing the vnode. |
356 | */ | 401 | */ |
357 | fc->ac.error = afs_register_server_cb_interest(vnode, fc->server_list, | 402 | error = afs_register_server_cb_interest(vnode, fc->server_list, |
358 | fc->index); | 403 | fc->index); |
359 | if (fc->ac.error < 0) | 404 | if (error < 0) |
360 | goto failed; | 405 | goto failed_set_error; |
361 | 406 | ||
362 | fc->cbi = afs_get_cb_interest(vnode->cb_interest); | 407 | fc->cbi = afs_get_cb_interest(vnode->cb_interest); |
363 | 408 | ||
@@ -369,66 +414,88 @@ use_server: | |||
369 | 414 | ||
370 | memset(&fc->ac, 0, sizeof(fc->ac)); | 415 | memset(&fc->ac, 0, sizeof(fc->ac)); |
371 | 416 | ||
372 | /* Probe the current fileserver if we haven't done so yet. */ | ||
373 | if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) { | ||
374 | fc->ac.alist = afs_get_addrlist(alist); | ||
375 | |||
376 | if (!afs_probe_fileserver(fc)) { | ||
377 | switch (fc->ac.error) { | ||
378 | case -ENOMEM: | ||
379 | case -ERESTARTSYS: | ||
380 | case -EINTR: | ||
381 | goto failed; | ||
382 | default: | ||
383 | goto next_server; | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | |||
388 | if (!fc->ac.alist) | 417 | if (!fc->ac.alist) |
389 | fc->ac.alist = alist; | 418 | fc->ac.alist = alist; |
390 | else | 419 | else |
391 | afs_put_addrlist(alist); | 420 | afs_put_addrlist(alist); |
392 | 421 | ||
393 | fc->ac.start = READ_ONCE(alist->index); | 422 | fc->ac.index = -1; |
394 | fc->ac.index = fc->ac.start; | ||
395 | 423 | ||
396 | iterate_address: | 424 | iterate_address: |
397 | ASSERT(fc->ac.alist); | 425 | ASSERT(fc->ac.alist); |
398 | _debug("iterate %d/%d", fc->ac.index, fc->ac.alist->nr_addrs); | ||
399 | /* Iterate over the current server's address list to try and find an | 426 | /* Iterate over the current server's address list to try and find an |
400 | * address on which it will respond to us. | 427 | * address on which it will respond to us. |
401 | */ | 428 | */ |
402 | if (!afs_iterate_addresses(&fc->ac)) | 429 | if (!afs_iterate_addresses(&fc->ac)) |
403 | goto next_server; | 430 | goto next_server; |
404 | 431 | ||
432 | _debug("address [%u] %u/%u", fc->index, fc->ac.index, fc->ac.alist->nr_addrs); | ||
433 | |||
405 | _leave(" = t"); | 434 | _leave(" = t"); |
406 | return true; | 435 | return true; |
407 | 436 | ||
408 | next_server: | 437 | next_server: |
409 | _debug("next"); | 438 | _debug("next"); |
410 | afs_end_cursor(&fc->ac); | 439 | afs_end_cursor(&fc->ac); |
411 | afs_put_cb_interest(afs_v2net(vnode), fc->cbi); | 440 | goto pick_server; |
412 | fc->cbi = NULL; | ||
413 | fc->index++; | ||
414 | if (fc->index >= fc->server_list->nr_servers) | ||
415 | fc->index = 0; | ||
416 | if (fc->index != fc->start) | ||
417 | goto use_server; | ||
418 | 441 | ||
442 | no_more_servers: | ||
419 | /* That's all the servers poked to no good effect. Try again if some | 443 | /* That's all the servers poked to no good effect. Try again if some |
420 | * of them were busy. | 444 | * of them were busy. |
421 | */ | 445 | */ |
422 | if (fc->flags & AFS_FS_CURSOR_VBUSY) | 446 | if (fc->flags & AFS_FS_CURSOR_VBUSY) |
423 | goto restart_from_beginning; | 447 | goto restart_from_beginning; |
424 | 448 | ||
425 | fc->ac.error = -EDESTADDRREQ; | 449 | abort_code = 0; |
426 | goto failed; | 450 | error = -EDESTADDRREQ; |
451 | for (i = 0; i < fc->server_list->nr_servers; i++) { | ||
452 | struct afs_server *s = fc->server_list->servers[i].server; | ||
453 | int probe_error = READ_ONCE(s->probe.error); | ||
454 | |||
455 | switch (probe_error) { | ||
456 | case 0: | ||
457 | continue; | ||
458 | default: | ||
459 | if (error == -ETIMEDOUT || | ||
460 | error == -ETIME) | ||
461 | continue; | ||
462 | case -ETIMEDOUT: | ||
463 | case -ETIME: | ||
464 | if (error == -ENOMEM || | ||
465 | error == -ENONET) | ||
466 | continue; | ||
467 | case -ENOMEM: | ||
468 | case -ENONET: | ||
469 | if (error == -ENETUNREACH) | ||
470 | continue; | ||
471 | case -ENETUNREACH: | ||
472 | if (error == -EHOSTUNREACH) | ||
473 | continue; | ||
474 | case -EHOSTUNREACH: | ||
475 | if (error == -ECONNREFUSED) | ||
476 | continue; | ||
477 | case -ECONNREFUSED: | ||
478 | if (error == -ECONNRESET) | ||
479 | continue; | ||
480 | case -ECONNRESET: /* Responded, but call expired. */ | ||
481 | if (error == -ECONNABORTED) | ||
482 | continue; | ||
483 | case -ECONNABORTED: | ||
484 | abort_code = s->probe.abort_code; | ||
485 | error = probe_error; | ||
486 | continue; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | if (error == -ECONNABORTED) | ||
491 | error = afs_abort_to_error(abort_code); | ||
427 | 492 | ||
493 | failed_set_error: | ||
494 | fc->error = error; | ||
428 | failed: | 495 | failed: |
429 | fc->flags |= AFS_FS_CURSOR_STOP; | 496 | fc->flags |= AFS_FS_CURSOR_STOP; |
430 | afs_end_cursor(&fc->ac); | 497 | afs_end_cursor(&fc->ac); |
431 | _leave(" = f [failed %d]", fc->ac.error); | 498 | _leave(" = f [failed %d]", fc->error); |
432 | return false; | 499 | return false; |
433 | } | 500 | } |
434 | 501 | ||
@@ -442,13 +509,14 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | |||
442 | struct afs_vnode *vnode = fc->vnode; | 509 | struct afs_vnode *vnode = fc->vnode; |
443 | struct afs_cb_interest *cbi = vnode->cb_interest; | 510 | struct afs_cb_interest *cbi = vnode->cb_interest; |
444 | struct afs_addr_list *alist; | 511 | struct afs_addr_list *alist; |
512 | int error = fc->ac.error; | ||
445 | 513 | ||
446 | _enter(""); | 514 | _enter(""); |
447 | 515 | ||
448 | switch (fc->ac.error) { | 516 | switch (error) { |
449 | case SHRT_MAX: | 517 | case SHRT_MAX: |
450 | if (!cbi) { | 518 | if (!cbi) { |
451 | fc->ac.error = -ESTALE; | 519 | fc->error = -ESTALE; |
452 | fc->flags |= AFS_FS_CURSOR_STOP; | 520 | fc->flags |= AFS_FS_CURSOR_STOP; |
453 | return false; | 521 | return false; |
454 | } | 522 | } |
@@ -461,25 +529,26 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | |||
461 | afs_get_addrlist(alist); | 529 | afs_get_addrlist(alist); |
462 | read_unlock(&cbi->server->fs_lock); | 530 | read_unlock(&cbi->server->fs_lock); |
463 | if (!alist) { | 531 | if (!alist) { |
464 | fc->ac.error = -ESTALE; | 532 | fc->error = -ESTALE; |
465 | fc->flags |= AFS_FS_CURSOR_STOP; | 533 | fc->flags |= AFS_FS_CURSOR_STOP; |
466 | return false; | 534 | return false; |
467 | } | 535 | } |
468 | 536 | ||
469 | memset(&fc->ac, 0, sizeof(fc->ac)); | 537 | memset(&fc->ac, 0, sizeof(fc->ac)); |
470 | fc->ac.alist = alist; | 538 | fc->ac.alist = alist; |
471 | fc->ac.start = READ_ONCE(alist->index); | 539 | fc->ac.index = -1; |
472 | fc->ac.index = fc->ac.start; | ||
473 | goto iterate_address; | 540 | goto iterate_address; |
474 | 541 | ||
475 | case 0: | 542 | case 0: |
476 | default: | 543 | default: |
477 | /* Success or local failure. Stop. */ | 544 | /* Success or local failure. Stop. */ |
545 | fc->error = error; | ||
478 | fc->flags |= AFS_FS_CURSOR_STOP; | 546 | fc->flags |= AFS_FS_CURSOR_STOP; |
479 | _leave(" = f [okay/local %d]", fc->ac.error); | 547 | _leave(" = f [okay/local %d]", error); |
480 | return false; | 548 | return false; |
481 | 549 | ||
482 | case -ECONNABORTED: | 550 | case -ECONNABORTED: |
551 | fc->error = afs_abort_to_error(fc->ac.abort_code); | ||
483 | fc->flags |= AFS_FS_CURSOR_STOP; | 552 | fc->flags |= AFS_FS_CURSOR_STOP; |
484 | _leave(" = f [abort]"); | 553 | _leave(" = f [abort]"); |
485 | return false; | 554 | return false; |
@@ -490,6 +559,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | |||
490 | case -ETIMEDOUT: | 559 | case -ETIMEDOUT: |
491 | case -ETIME: | 560 | case -ETIME: |
492 | _debug("no conn"); | 561 | _debug("no conn"); |
562 | fc->error = error; | ||
493 | goto iterate_address; | 563 | goto iterate_address; |
494 | } | 564 | } |
495 | 565 | ||
@@ -507,12 +577,65 @@ iterate_address: | |||
507 | } | 577 | } |
508 | 578 | ||
509 | /* | 579 | /* |
580 | * Dump cursor state in the case of the error being EDESTADDRREQ. | ||
581 | */ | ||
582 | static void afs_dump_edestaddrreq(const struct afs_fs_cursor *fc) | ||
583 | { | ||
584 | static int count; | ||
585 | int i; | ||
586 | |||
587 | if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3) | ||
588 | return; | ||
589 | count++; | ||
590 | |||
591 | rcu_read_lock(); | ||
592 | |||
593 | pr_notice("EDESTADDR occurred\n"); | ||
594 | pr_notice("FC: cbb=%x cbb2=%x fl=%hx err=%hd\n", | ||
595 | fc->cb_break, fc->cb_break_2, fc->flags, fc->error); | ||
596 | pr_notice("FC: ut=%lx ix=%d ni=%u\n", | ||
597 | fc->untried, fc->index, fc->nr_iterations); | ||
598 | |||
599 | if (fc->server_list) { | ||
600 | const struct afs_server_list *sl = fc->server_list; | ||
601 | pr_notice("FC: SL nr=%u pr=%u vnov=%hx\n", | ||
602 | sl->nr_servers, sl->preferred, sl->vnovol_mask); | ||
603 | for (i = 0; i < sl->nr_servers; i++) { | ||
604 | const struct afs_server *s = sl->servers[i].server; | ||
605 | pr_notice("FC: server fl=%lx av=%u %pU\n", | ||
606 | s->flags, s->addr_version, &s->uuid); | ||
607 | if (s->addresses) { | ||
608 | const struct afs_addr_list *a = | ||
609 | rcu_dereference(s->addresses); | ||
610 | pr_notice("FC: - av=%u nr=%u/%u/%u pr=%u\n", | ||
611 | a->version, | ||
612 | a->nr_ipv4, a->nr_addrs, a->max_addrs, | ||
613 | a->preferred); | ||
614 | pr_notice("FC: - pr=%lx R=%lx F=%lx\n", | ||
615 | a->probed, a->responded, a->failed); | ||
616 | if (a == fc->ac.alist) | ||
617 | pr_notice("FC: - current\n"); | ||
618 | } | ||
619 | } | ||
620 | } | ||
621 | |||
622 | pr_notice("AC: t=%lx ax=%u ac=%d er=%d r=%u ni=%u\n", | ||
623 | fc->ac.tried, fc->ac.index, fc->ac.abort_code, fc->ac.error, | ||
624 | fc->ac.responded, fc->ac.nr_iterations); | ||
625 | rcu_read_unlock(); | ||
626 | } | ||
627 | |||
628 | /* | ||
510 | * Tidy up a filesystem cursor and unlock the vnode. | 629 | * Tidy up a filesystem cursor and unlock the vnode. |
511 | */ | 630 | */ |
512 | int afs_end_vnode_operation(struct afs_fs_cursor *fc) | 631 | int afs_end_vnode_operation(struct afs_fs_cursor *fc) |
513 | { | 632 | { |
514 | struct afs_net *net = afs_v2net(fc->vnode); | 633 | struct afs_net *net = afs_v2net(fc->vnode); |
515 | int ret; | 634 | |
635 | if (fc->error == -EDESTADDRREQ || | ||
636 | fc->error == -ENETUNREACH || | ||
637 | fc->error == -EHOSTUNREACH) | ||
638 | afs_dump_edestaddrreq(fc); | ||
516 | 639 | ||
517 | mutex_unlock(&fc->vnode->io_lock); | 640 | mutex_unlock(&fc->vnode->io_lock); |
518 | 641 | ||
@@ -520,9 +643,8 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc) | |||
520 | afs_put_cb_interest(net, fc->cbi); | 643 | afs_put_cb_interest(net, fc->cbi); |
521 | afs_put_serverlist(net, fc->server_list); | 644 | afs_put_serverlist(net, fc->server_list); |
522 | 645 | ||
523 | ret = fc->ac.error; | 646 | if (fc->error == -ECONNABORTED) |
524 | if (ret == -ECONNABORTED) | 647 | fc->error = afs_abort_to_error(fc->ac.abort_code); |
525 | afs_abort_to_error(fc->ac.abort_code); | ||
526 | 648 | ||
527 | return fc->ac.error; | 649 | return fc->error; |
528 | } | 650 | } |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 77a83790a31f..59970886690f 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <net/af_rxrpc.h> | 16 | #include <net/af_rxrpc.h> |
17 | #include "internal.h" | 17 | #include "internal.h" |
18 | #include "afs_cm.h" | 18 | #include "afs_cm.h" |
19 | #include "protocol_yfs.h" | ||
19 | 20 | ||
20 | struct workqueue_struct *afs_async_calls; | 21 | struct workqueue_struct *afs_async_calls; |
21 | 22 | ||
@@ -75,6 +76,18 @@ int afs_open_socket(struct afs_net *net) | |||
75 | if (ret < 0) | 76 | if (ret < 0) |
76 | goto error_2; | 77 | goto error_2; |
77 | 78 | ||
79 | srx.srx_service = YFS_CM_SERVICE; | ||
80 | ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx)); | ||
81 | if (ret < 0) | ||
82 | goto error_2; | ||
83 | |||
84 | /* Ideally, we'd turn on service upgrade here, but we can't because | ||
85 | * OpenAFS is buggy and leaks the userStatus field from packet to | ||
86 | * packet and between FS packets and CB packets - so if we try to do an | ||
87 | * upgrade on an FS packet, OpenAFS will leak that into the CB packet | ||
88 | * it sends back to us. | ||
89 | */ | ||
90 | |||
78 | rxrpc_kernel_new_call_notification(socket, afs_rx_new_call, | 91 | rxrpc_kernel_new_call_notification(socket, afs_rx_new_call, |
79 | afs_rx_discard_new_call); | 92 | afs_rx_discard_new_call); |
80 | 93 | ||
@@ -143,6 +156,7 @@ static struct afs_call *afs_alloc_call(struct afs_net *net, | |||
143 | INIT_WORK(&call->async_work, afs_process_async_call); | 156 | INIT_WORK(&call->async_work, afs_process_async_call); |
144 | init_waitqueue_head(&call->waitq); | 157 | init_waitqueue_head(&call->waitq); |
145 | spin_lock_init(&call->state_lock); | 158 | spin_lock_init(&call->state_lock); |
159 | call->_iter = &call->iter; | ||
146 | 160 | ||
147 | o = atomic_inc_return(&net->nr_outstanding_calls); | 161 | o = atomic_inc_return(&net->nr_outstanding_calls); |
148 | trace_afs_call(call, afs_call_trace_alloc, 1, o, | 162 | trace_afs_call(call, afs_call_trace_alloc, 1, o, |
@@ -176,6 +190,7 @@ void afs_put_call(struct afs_call *call) | |||
176 | 190 | ||
177 | afs_put_server(call->net, call->cm_server); | 191 | afs_put_server(call->net, call->cm_server); |
178 | afs_put_cb_interest(call->net, call->cbi); | 192 | afs_put_cb_interest(call->net, call->cbi); |
193 | afs_put_addrlist(call->alist); | ||
179 | kfree(call->request); | 194 | kfree(call->request); |
180 | 195 | ||
181 | trace_afs_call(call, afs_call_trace_free, 0, o, | 196 | trace_afs_call(call, afs_call_trace_free, 0, o, |
@@ -189,21 +204,22 @@ void afs_put_call(struct afs_call *call) | |||
189 | } | 204 | } |
190 | 205 | ||
191 | /* | 206 | /* |
192 | * Queue the call for actual work. Returns 0 unconditionally for convenience. | 207 | * Queue the call for actual work. |
193 | */ | 208 | */ |
194 | int afs_queue_call_work(struct afs_call *call) | 209 | static void afs_queue_call_work(struct afs_call *call) |
195 | { | 210 | { |
196 | int u = atomic_inc_return(&call->usage); | 211 | if (call->type->work) { |
212 | int u = atomic_inc_return(&call->usage); | ||
197 | 213 | ||
198 | trace_afs_call(call, afs_call_trace_work, u, | 214 | trace_afs_call(call, afs_call_trace_work, u, |
199 | atomic_read(&call->net->nr_outstanding_calls), | 215 | atomic_read(&call->net->nr_outstanding_calls), |
200 | __builtin_return_address(0)); | 216 | __builtin_return_address(0)); |
201 | 217 | ||
202 | INIT_WORK(&call->work, call->type->work); | 218 | INIT_WORK(&call->work, call->type->work); |
203 | 219 | ||
204 | if (!queue_work(afs_wq, &call->work)) | 220 | if (!queue_work(afs_wq, &call->work)) |
205 | afs_put_call(call); | 221 | afs_put_call(call); |
206 | return 0; | 222 | } |
207 | } | 223 | } |
208 | 224 | ||
209 | /* | 225 | /* |
@@ -233,6 +249,7 @@ struct afs_call *afs_alloc_flat_call(struct afs_net *net, | |||
233 | goto nomem_free; | 249 | goto nomem_free; |
234 | } | 250 | } |
235 | 251 | ||
252 | afs_extract_to_buf(call, call->reply_max); | ||
236 | call->operation_ID = type->op; | 253 | call->operation_ID = type->op; |
237 | init_waitqueue_head(&call->waitq); | 254 | init_waitqueue_head(&call->waitq); |
238 | return call; | 255 | return call; |
@@ -286,7 +303,7 @@ static void afs_load_bvec(struct afs_call *call, struct msghdr *msg, | |||
286 | offset = 0; | 303 | offset = 0; |
287 | } | 304 | } |
288 | 305 | ||
289 | iov_iter_bvec(&msg->msg_iter, WRITE | ITER_BVEC, bv, nr, bytes); | 306 | iov_iter_bvec(&msg->msg_iter, WRITE, bv, nr, bytes); |
290 | } | 307 | } |
291 | 308 | ||
292 | /* | 309 | /* |
@@ -342,7 +359,7 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg) | |||
342 | long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, | 359 | long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, |
343 | gfp_t gfp, bool async) | 360 | gfp_t gfp, bool async) |
344 | { | 361 | { |
345 | struct sockaddr_rxrpc *srx = ac->addr; | 362 | struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index]; |
346 | struct rxrpc_call *rxcall; | 363 | struct rxrpc_call *rxcall; |
347 | struct msghdr msg; | 364 | struct msghdr msg; |
348 | struct kvec iov[1]; | 365 | struct kvec iov[1]; |
@@ -359,6 +376,8 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, | |||
359 | atomic_read(&call->net->nr_outstanding_calls)); | 376 | atomic_read(&call->net->nr_outstanding_calls)); |
360 | 377 | ||
361 | call->async = async; | 378 | call->async = async; |
379 | call->addr_ix = ac->index; | ||
380 | call->alist = afs_get_addrlist(ac->alist); | ||
362 | 381 | ||
363 | /* Work out the length we're going to transmit. This is awkward for | 382 | /* Work out the length we're going to transmit. This is awkward for |
364 | * calls such as FS.StoreData where there's an extra injection of data | 383 | * calls such as FS.StoreData where there's an extra injection of data |
@@ -390,6 +409,7 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, | |||
390 | call->debug_id); | 409 | call->debug_id); |
391 | if (IS_ERR(rxcall)) { | 410 | if (IS_ERR(rxcall)) { |
392 | ret = PTR_ERR(rxcall); | 411 | ret = PTR_ERR(rxcall); |
412 | call->error = ret; | ||
393 | goto error_kill_call; | 413 | goto error_kill_call; |
394 | } | 414 | } |
395 | 415 | ||
@@ -401,8 +421,7 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, | |||
401 | 421 | ||
402 | msg.msg_name = NULL; | 422 | msg.msg_name = NULL; |
403 | msg.msg_namelen = 0; | 423 | msg.msg_namelen = 0; |
404 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iov, 1, | 424 | iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, call->request_size); |
405 | call->request_size); | ||
406 | msg.msg_control = NULL; | 425 | msg.msg_control = NULL; |
407 | msg.msg_controllen = 0; | 426 | msg.msg_controllen = 0; |
408 | msg.msg_flags = MSG_WAITALL | (call->send_pages ? MSG_MORE : 0); | 427 | msg.msg_flags = MSG_WAITALL | (call->send_pages ? MSG_MORE : 0); |
@@ -432,7 +451,7 @@ error_do_abort: | |||
432 | rxrpc_kernel_abort_call(call->net->socket, rxcall, | 451 | rxrpc_kernel_abort_call(call->net->socket, rxcall, |
433 | RX_USER_ABORT, ret, "KSD"); | 452 | RX_USER_ABORT, ret, "KSD"); |
434 | } else { | 453 | } else { |
435 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, NULL, 0, 0); | 454 | iov_iter_kvec(&msg.msg_iter, READ, NULL, 0, 0); |
436 | rxrpc_kernel_recv_data(call->net->socket, rxcall, | 455 | rxrpc_kernel_recv_data(call->net->socket, rxcall, |
437 | &msg.msg_iter, false, | 456 | &msg.msg_iter, false, |
438 | &call->abort_code, &call->service_id); | 457 | &call->abort_code, &call->service_id); |
@@ -442,6 +461,8 @@ error_do_abort: | |||
442 | call->error = ret; | 461 | call->error = ret; |
443 | trace_afs_call_done(call); | 462 | trace_afs_call_done(call); |
444 | error_kill_call: | 463 | error_kill_call: |
464 | if (call->type->done) | ||
465 | call->type->done(call); | ||
445 | afs_put_call(call); | 466 | afs_put_call(call); |
446 | ac->error = ret; | 467 | ac->error = ret; |
447 | _leave(" = %d", ret); | 468 | _leave(" = %d", ret); |
@@ -466,14 +487,12 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
466 | state == AFS_CALL_SV_AWAIT_ACK | 487 | state == AFS_CALL_SV_AWAIT_ACK |
467 | ) { | 488 | ) { |
468 | if (state == AFS_CALL_SV_AWAIT_ACK) { | 489 | if (state == AFS_CALL_SV_AWAIT_ACK) { |
469 | struct iov_iter iter; | 490 | iov_iter_kvec(&call->iter, READ, NULL, 0, 0); |
470 | |||
471 | iov_iter_kvec(&iter, READ | ITER_KVEC, NULL, 0, 0); | ||
472 | ret = rxrpc_kernel_recv_data(call->net->socket, | 491 | ret = rxrpc_kernel_recv_data(call->net->socket, |
473 | call->rxcall, &iter, false, | 492 | call->rxcall, &call->iter, |
474 | &remote_abort, | 493 | false, &remote_abort, |
475 | &call->service_id); | 494 | &call->service_id); |
476 | trace_afs_recv_data(call, 0, 0, false, ret); | 495 | trace_afs_receive_data(call, &call->iter, false, ret); |
477 | 496 | ||
478 | if (ret == -EINPROGRESS || ret == -EAGAIN) | 497 | if (ret == -EINPROGRESS || ret == -EAGAIN) |
479 | return; | 498 | return; |
@@ -485,10 +504,17 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
485 | return; | 504 | return; |
486 | } | 505 | } |
487 | 506 | ||
507 | if (call->want_reply_time && | ||
508 | rxrpc_kernel_get_reply_time(call->net->socket, | ||
509 | call->rxcall, | ||
510 | &call->reply_time)) | ||
511 | call->want_reply_time = false; | ||
512 | |||
488 | ret = call->type->deliver(call); | 513 | ret = call->type->deliver(call); |
489 | state = READ_ONCE(call->state); | 514 | state = READ_ONCE(call->state); |
490 | switch (ret) { | 515 | switch (ret) { |
491 | case 0: | 516 | case 0: |
517 | afs_queue_call_work(call); | ||
492 | if (state == AFS_CALL_CL_PROC_REPLY) { | 518 | if (state == AFS_CALL_CL_PROC_REPLY) { |
493 | if (call->cbi) | 519 | if (call->cbi) |
494 | set_bit(AFS_SERVER_FL_MAY_HAVE_CB, | 520 | set_bit(AFS_SERVER_FL_MAY_HAVE_CB, |
@@ -500,7 +526,6 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
500 | case -EINPROGRESS: | 526 | case -EINPROGRESS: |
501 | case -EAGAIN: | 527 | case -EAGAIN: |
502 | goto out; | 528 | goto out; |
503 | case -EIO: | ||
504 | case -ECONNABORTED: | 529 | case -ECONNABORTED: |
505 | ASSERTCMP(state, ==, AFS_CALL_COMPLETE); | 530 | ASSERTCMP(state, ==, AFS_CALL_COMPLETE); |
506 | goto done; | 531 | goto done; |
@@ -509,6 +534,10 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
509 | rxrpc_kernel_abort_call(call->net->socket, call->rxcall, | 534 | rxrpc_kernel_abort_call(call->net->socket, call->rxcall, |
510 | abort_code, ret, "KIV"); | 535 | abort_code, ret, "KIV"); |
511 | goto local_abort; | 536 | goto local_abort; |
537 | case -EIO: | ||
538 | pr_err("kAFS: Call %u in bad state %u\n", | ||
539 | call->debug_id, state); | ||
540 | /* Fall through */ | ||
512 | case -ENODATA: | 541 | case -ENODATA: |
513 | case -EBADMSG: | 542 | case -EBADMSG: |
514 | case -EMSGSIZE: | 543 | case -EMSGSIZE: |
@@ -517,12 +546,14 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
517 | if (state != AFS_CALL_CL_AWAIT_REPLY) | 546 | if (state != AFS_CALL_CL_AWAIT_REPLY) |
518 | abort_code = RXGEN_SS_UNMARSHAL; | 547 | abort_code = RXGEN_SS_UNMARSHAL; |
519 | rxrpc_kernel_abort_call(call->net->socket, call->rxcall, | 548 | rxrpc_kernel_abort_call(call->net->socket, call->rxcall, |
520 | abort_code, -EBADMSG, "KUM"); | 549 | abort_code, ret, "KUM"); |
521 | goto local_abort; | 550 | goto local_abort; |
522 | } | 551 | } |
523 | } | 552 | } |
524 | 553 | ||
525 | done: | 554 | done: |
555 | if (call->type->done) | ||
556 | call->type->done(call); | ||
526 | if (state == AFS_CALL_COMPLETE && call->incoming) | 557 | if (state == AFS_CALL_COMPLETE && call->incoming) |
527 | afs_put_call(call); | 558 | afs_put_call(call); |
528 | out: | 559 | out: |
@@ -728,6 +759,7 @@ void afs_charge_preallocation(struct work_struct *work) | |||
728 | call->async = true; | 759 | call->async = true; |
729 | call->state = AFS_CALL_SV_AWAIT_OP_ID; | 760 | call->state = AFS_CALL_SV_AWAIT_OP_ID; |
730 | init_waitqueue_head(&call->waitq); | 761 | init_waitqueue_head(&call->waitq); |
762 | afs_extract_to_tmp(call); | ||
731 | } | 763 | } |
732 | 764 | ||
733 | if (rxrpc_kernel_charge_accept(net->socket, | 765 | if (rxrpc_kernel_charge_accept(net->socket, |
@@ -773,18 +805,15 @@ static int afs_deliver_cm_op_id(struct afs_call *call) | |||
773 | { | 805 | { |
774 | int ret; | 806 | int ret; |
775 | 807 | ||
776 | _enter("{%zu}", call->offset); | 808 | _enter("{%zu}", iov_iter_count(call->_iter)); |
777 | |||
778 | ASSERTCMP(call->offset, <, 4); | ||
779 | 809 | ||
780 | /* the operation ID forms the first four bytes of the request data */ | 810 | /* the operation ID forms the first four bytes of the request data */ |
781 | ret = afs_extract_data(call, &call->tmp, 4, true); | 811 | ret = afs_extract_data(call, true); |
782 | if (ret < 0) | 812 | if (ret < 0) |
783 | return ret; | 813 | return ret; |
784 | 814 | ||
785 | call->operation_ID = ntohl(call->tmp); | 815 | call->operation_ID = ntohl(call->tmp); |
786 | afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST); | 816 | afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST); |
787 | call->offset = 0; | ||
788 | 817 | ||
789 | /* ask the cache manager to route the call (it'll change the call type | 818 | /* ask the cache manager to route the call (it'll change the call type |
790 | * if successful) */ | 819 | * if successful) */ |
@@ -825,7 +854,7 @@ void afs_send_empty_reply(struct afs_call *call) | |||
825 | 854 | ||
826 | msg.msg_name = NULL; | 855 | msg.msg_name = NULL; |
827 | msg.msg_namelen = 0; | 856 | msg.msg_namelen = 0; |
828 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, NULL, 0, 0); | 857 | iov_iter_kvec(&msg.msg_iter, WRITE, NULL, 0, 0); |
829 | msg.msg_control = NULL; | 858 | msg.msg_control = NULL; |
830 | msg.msg_controllen = 0; | 859 | msg.msg_controllen = 0; |
831 | msg.msg_flags = 0; | 860 | msg.msg_flags = 0; |
@@ -864,7 +893,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) | |||
864 | iov[0].iov_len = len; | 893 | iov[0].iov_len = len; |
865 | msg.msg_name = NULL; | 894 | msg.msg_name = NULL; |
866 | msg.msg_namelen = 0; | 895 | msg.msg_namelen = 0; |
867 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iov, 1, len); | 896 | iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len); |
868 | msg.msg_control = NULL; | 897 | msg.msg_control = NULL; |
869 | msg.msg_controllen = 0; | 898 | msg.msg_controllen = 0; |
870 | msg.msg_flags = 0; | 899 | msg.msg_flags = 0; |
@@ -888,30 +917,19 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) | |||
888 | /* | 917 | /* |
889 | * Extract a piece of data from the received data socket buffers. | 918 | * Extract a piece of data from the received data socket buffers. |
890 | */ | 919 | */ |
891 | int afs_extract_data(struct afs_call *call, void *buf, size_t count, | 920 | int afs_extract_data(struct afs_call *call, bool want_more) |
892 | bool want_more) | ||
893 | { | 921 | { |
894 | struct afs_net *net = call->net; | 922 | struct afs_net *net = call->net; |
895 | struct iov_iter iter; | 923 | struct iov_iter *iter = call->_iter; |
896 | struct kvec iov; | ||
897 | enum afs_call_state state; | 924 | enum afs_call_state state; |
898 | u32 remote_abort = 0; | 925 | u32 remote_abort = 0; |
899 | int ret; | 926 | int ret; |
900 | 927 | ||
901 | _enter("{%s,%zu},,%zu,%d", | 928 | _enter("{%s,%zu},%d", call->type->name, iov_iter_count(iter), want_more); |
902 | call->type->name, call->offset, count, want_more); | ||
903 | |||
904 | ASSERTCMP(call->offset, <=, count); | ||
905 | |||
906 | iov.iov_base = buf + call->offset; | ||
907 | iov.iov_len = count - call->offset; | ||
908 | iov_iter_kvec(&iter, ITER_KVEC | READ, &iov, 1, count - call->offset); | ||
909 | 929 | ||
910 | ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, &iter, | 930 | ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter, |
911 | want_more, &remote_abort, | 931 | want_more, &remote_abort, |
912 | &call->service_id); | 932 | &call->service_id); |
913 | call->offset += (count - call->offset) - iov_iter_count(&iter); | ||
914 | trace_afs_recv_data(call, count, call->offset, want_more, ret); | ||
915 | if (ret == 0 || ret == -EAGAIN) | 933 | if (ret == 0 || ret == -EAGAIN) |
916 | return ret; | 934 | return ret; |
917 | 935 | ||
@@ -926,7 +944,7 @@ int afs_extract_data(struct afs_call *call, void *buf, size_t count, | |||
926 | break; | 944 | break; |
927 | case AFS_CALL_COMPLETE: | 945 | case AFS_CALL_COMPLETE: |
928 | kdebug("prem complete %d", call->error); | 946 | kdebug("prem complete %d", call->error); |
929 | return -EIO; | 947 | return afs_io_error(call, afs_io_error_extract); |
930 | default: | 948 | default: |
931 | break; | 949 | break; |
932 | } | 950 | } |
@@ -940,8 +958,9 @@ int afs_extract_data(struct afs_call *call, void *buf, size_t count, | |||
940 | /* | 958 | /* |
941 | * Log protocol error production. | 959 | * Log protocol error production. |
942 | */ | 960 | */ |
943 | noinline int afs_protocol_error(struct afs_call *call, int error) | 961 | noinline int afs_protocol_error(struct afs_call *call, int error, |
962 | enum afs_eproto_cause cause) | ||
944 | { | 963 | { |
945 | trace_afs_protocol_error(call, error, __builtin_return_address(0)); | 964 | trace_afs_protocol_error(call, error, cause); |
946 | return error; | 965 | return error; |
947 | } | 966 | } |
diff --git a/fs/afs/security.c b/fs/afs/security.c index 81dfedb7879f..5f58a9a17e69 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c | |||
@@ -126,7 +126,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | |||
126 | bool changed = false; | 126 | bool changed = false; |
127 | int i, j; | 127 | int i, j; |
128 | 128 | ||
129 | _enter("{%x:%u},%x,%x", | 129 | _enter("{%llx:%llu},%x,%x", |
130 | vnode->fid.vid, vnode->fid.vnode, key_serial(key), caller_access); | 130 | vnode->fid.vid, vnode->fid.vnode, key_serial(key), caller_access); |
131 | 131 | ||
132 | rcu_read_lock(); | 132 | rcu_read_lock(); |
@@ -147,7 +147,8 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | |||
147 | break; | 147 | break; |
148 | } | 148 | } |
149 | 149 | ||
150 | if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest)) { | 150 | if (afs_cb_is_broken(cb_break, vnode, |
151 | vnode->cb_interest)) { | ||
151 | changed = true; | 152 | changed = true; |
152 | break; | 153 | break; |
153 | } | 154 | } |
@@ -177,7 +178,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | |||
177 | } | 178 | } |
178 | } | 179 | } |
179 | 180 | ||
180 | if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest)) | 181 | if (afs_cb_is_broken(cb_break, vnode, vnode->cb_interest)) |
181 | goto someone_else_changed_it; | 182 | goto someone_else_changed_it; |
182 | 183 | ||
183 | /* We need a ref on any permits list we want to copy as we'll have to | 184 | /* We need a ref on any permits list we want to copy as we'll have to |
@@ -256,7 +257,7 @@ found: | |||
256 | 257 | ||
257 | spin_lock(&vnode->lock); | 258 | spin_lock(&vnode->lock); |
258 | zap = rcu_access_pointer(vnode->permit_cache); | 259 | zap = rcu_access_pointer(vnode->permit_cache); |
259 | if (cb_break == afs_cb_break_sum(vnode, vnode->cb_interest) && | 260 | if (!afs_cb_is_broken(cb_break, vnode, vnode->cb_interest) && |
260 | zap == permits) | 261 | zap == permits) |
261 | rcu_assign_pointer(vnode->permit_cache, replacement); | 262 | rcu_assign_pointer(vnode->permit_cache, replacement); |
262 | else | 263 | else |
@@ -289,7 +290,7 @@ int afs_check_permit(struct afs_vnode *vnode, struct key *key, | |||
289 | bool valid = false; | 290 | bool valid = false; |
290 | int i, ret; | 291 | int i, ret; |
291 | 292 | ||
292 | _enter("{%x:%u},%x", | 293 | _enter("{%llx:%llu},%x", |
293 | vnode->fid.vid, vnode->fid.vnode, key_serial(key)); | 294 | vnode->fid.vid, vnode->fid.vnode, key_serial(key)); |
294 | 295 | ||
295 | /* check the permits to see if we've got one yet */ | 296 | /* check the permits to see if we've got one yet */ |
@@ -349,7 +350,7 @@ int afs_permission(struct inode *inode, int mask) | |||
349 | if (mask & MAY_NOT_BLOCK) | 350 | if (mask & MAY_NOT_BLOCK) |
350 | return -ECHILD; | 351 | return -ECHILD; |
351 | 352 | ||
352 | _enter("{{%x:%u},%lx},%x,", | 353 | _enter("{{%llx:%llu},%lx},%x,", |
353 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask); | 354 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask); |
354 | 355 | ||
355 | key = afs_request_key(vnode->volume->cell); | 356 | key = afs_request_key(vnode->volume->cell); |
diff --git a/fs/afs/server.c b/fs/afs/server.c index 1d329e6981d5..642afa2e9783 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include "afs_fs.h" | 14 | #include "afs_fs.h" |
15 | #include "internal.h" | 15 | #include "internal.h" |
16 | #include "protocol_yfs.h" | ||
16 | 17 | ||
17 | static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */ | 18 | static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */ |
18 | static unsigned afs_server_update_delay = 30; /* Time till VLDB recheck in secs */ | 19 | static unsigned afs_server_update_delay = 30; /* Time till VLDB recheck in secs */ |
@@ -230,6 +231,8 @@ static struct afs_server *afs_alloc_server(struct afs_net *net, | |||
230 | rwlock_init(&server->fs_lock); | 231 | rwlock_init(&server->fs_lock); |
231 | INIT_HLIST_HEAD(&server->cb_volumes); | 232 | INIT_HLIST_HEAD(&server->cb_volumes); |
232 | rwlock_init(&server->cb_break_lock); | 233 | rwlock_init(&server->cb_break_lock); |
234 | init_waitqueue_head(&server->probe_wq); | ||
235 | spin_lock_init(&server->probe_lock); | ||
233 | 236 | ||
234 | afs_inc_servers_outstanding(net); | 237 | afs_inc_servers_outstanding(net); |
235 | _leave(" = %p", server); | 238 | _leave(" = %p", server); |
@@ -246,41 +249,23 @@ enomem: | |||
246 | static struct afs_addr_list *afs_vl_lookup_addrs(struct afs_cell *cell, | 249 | static struct afs_addr_list *afs_vl_lookup_addrs(struct afs_cell *cell, |
247 | struct key *key, const uuid_t *uuid) | 250 | struct key *key, const uuid_t *uuid) |
248 | { | 251 | { |
249 | struct afs_addr_cursor ac; | 252 | struct afs_vl_cursor vc; |
250 | struct afs_addr_list *alist; | 253 | struct afs_addr_list *alist = NULL; |
251 | int ret; | 254 | int ret; |
252 | 255 | ||
253 | ret = afs_set_vl_cursor(&ac, cell); | 256 | ret = -ERESTARTSYS; |
254 | if (ret < 0) | 257 | if (afs_begin_vlserver_operation(&vc, cell, key)) { |
255 | return ERR_PTR(ret); | 258 | while (afs_select_vlserver(&vc)) { |
256 | 259 | if (test_bit(AFS_VLSERVER_FL_IS_YFS, &vc.server->flags)) | |
257 | while (afs_iterate_addresses(&ac)) { | 260 | alist = afs_yfsvl_get_endpoints(&vc, uuid); |
258 | if (test_bit(ac.index, &ac.alist->yfs)) | 261 | else |
259 | alist = afs_yfsvl_get_endpoints(cell->net, &ac, key, uuid); | 262 | alist = afs_vl_get_addrs_u(&vc, uuid); |
260 | else | ||
261 | alist = afs_vl_get_addrs_u(cell->net, &ac, key, uuid); | ||
262 | switch (ac.error) { | ||
263 | case 0: | ||
264 | afs_end_cursor(&ac); | ||
265 | return alist; | ||
266 | case -ECONNABORTED: | ||
267 | ac.error = afs_abort_to_error(ac.abort_code); | ||
268 | goto error; | ||
269 | case -ENOMEM: | ||
270 | case -ENONET: | ||
271 | goto error; | ||
272 | case -ENETUNREACH: | ||
273 | case -EHOSTUNREACH: | ||
274 | case -ECONNREFUSED: | ||
275 | break; | ||
276 | default: | ||
277 | ac.error = -EIO; | ||
278 | goto error; | ||
279 | } | 263 | } |
264 | |||
265 | ret = afs_end_vlserver_operation(&vc); | ||
280 | } | 266 | } |
281 | 267 | ||
282 | error: | 268 | return ret < 0 ? ERR_PTR(ret) : alist; |
283 | return ERR_PTR(afs_end_cursor(&ac)); | ||
284 | } | 269 | } |
285 | 270 | ||
286 | /* | 271 | /* |
@@ -382,9 +367,7 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) | |||
382 | struct afs_addr_list *alist = rcu_access_pointer(server->addresses); | 367 | struct afs_addr_list *alist = rcu_access_pointer(server->addresses); |
383 | struct afs_addr_cursor ac = { | 368 | struct afs_addr_cursor ac = { |
384 | .alist = alist, | 369 | .alist = alist, |
385 | .start = alist->index, | 370 | .index = alist->preferred, |
386 | .index = 0, | ||
387 | .addr = &alist->addrs[alist->index], | ||
388 | .error = 0, | 371 | .error = 0, |
389 | }; | 372 | }; |
390 | _enter("%p", server); | 373 | _enter("%p", server); |
@@ -392,6 +375,9 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) | |||
392 | if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) | 375 | if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) |
393 | afs_fs_give_up_all_callbacks(net, server, &ac, NULL); | 376 | afs_fs_give_up_all_callbacks(net, server, &ac, NULL); |
394 | 377 | ||
378 | wait_var_event(&server->probe_outstanding, | ||
379 | atomic_read(&server->probe_outstanding) == 0); | ||
380 | |||
395 | call_rcu(&server->rcu, afs_server_rcu); | 381 | call_rcu(&server->rcu, afs_server_rcu); |
396 | afs_dec_servers_outstanding(net); | 382 | afs_dec_servers_outstanding(net); |
397 | } | 383 | } |
@@ -525,99 +511,6 @@ void afs_purge_servers(struct afs_net *net) | |||
525 | } | 511 | } |
526 | 512 | ||
527 | /* | 513 | /* |
528 | * Probe a fileserver to find its capabilities. | ||
529 | * | ||
530 | * TODO: Try service upgrade. | ||
531 | */ | ||
532 | static bool afs_do_probe_fileserver(struct afs_fs_cursor *fc) | ||
533 | { | ||
534 | _enter(""); | ||
535 | |||
536 | fc->ac.addr = NULL; | ||
537 | fc->ac.start = READ_ONCE(fc->ac.alist->index); | ||
538 | fc->ac.index = fc->ac.start; | ||
539 | fc->ac.error = 0; | ||
540 | fc->ac.begun = false; | ||
541 | |||
542 | while (afs_iterate_addresses(&fc->ac)) { | ||
543 | afs_fs_get_capabilities(afs_v2net(fc->vnode), fc->cbi->server, | ||
544 | &fc->ac, fc->key); | ||
545 | switch (fc->ac.error) { | ||
546 | case 0: | ||
547 | afs_end_cursor(&fc->ac); | ||
548 | set_bit(AFS_SERVER_FL_PROBED, &fc->cbi->server->flags); | ||
549 | return true; | ||
550 | case -ECONNABORTED: | ||
551 | fc->ac.error = afs_abort_to_error(fc->ac.abort_code); | ||
552 | goto error; | ||
553 | case -ENOMEM: | ||
554 | case -ENONET: | ||
555 | goto error; | ||
556 | case -ENETUNREACH: | ||
557 | case -EHOSTUNREACH: | ||
558 | case -ECONNREFUSED: | ||
559 | case -ETIMEDOUT: | ||
560 | case -ETIME: | ||
561 | break; | ||
562 | default: | ||
563 | fc->ac.error = -EIO; | ||
564 | goto error; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | error: | ||
569 | afs_end_cursor(&fc->ac); | ||
570 | return false; | ||
571 | } | ||
572 | |||
573 | /* | ||
574 | * If we haven't already, try probing the fileserver to get its capabilities. | ||
575 | * We try not to instigate parallel probes, but it's possible that the parallel | ||
576 | * probes will fail due to authentication failure when ours would succeed. | ||
577 | * | ||
578 | * TODO: Try sending an anonymous probe if an authenticated probe fails. | ||
579 | */ | ||
580 | bool afs_probe_fileserver(struct afs_fs_cursor *fc) | ||
581 | { | ||
582 | bool success; | ||
583 | int ret, retries = 0; | ||
584 | |||
585 | _enter(""); | ||
586 | |||
587 | retry: | ||
588 | if (test_bit(AFS_SERVER_FL_PROBED, &fc->cbi->server->flags)) { | ||
589 | _leave(" = t"); | ||
590 | return true; | ||
591 | } | ||
592 | |||
593 | if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &fc->cbi->server->flags)) { | ||
594 | success = afs_do_probe_fileserver(fc); | ||
595 | clear_bit_unlock(AFS_SERVER_FL_PROBING, &fc->cbi->server->flags); | ||
596 | wake_up_bit(&fc->cbi->server->flags, AFS_SERVER_FL_PROBING); | ||
597 | _leave(" = t"); | ||
598 | return success; | ||
599 | } | ||
600 | |||
601 | _debug("wait"); | ||
602 | ret = wait_on_bit(&fc->cbi->server->flags, AFS_SERVER_FL_PROBING, | ||
603 | TASK_INTERRUPTIBLE); | ||
604 | if (ret == -ERESTARTSYS) { | ||
605 | fc->ac.error = ret; | ||
606 | _leave(" = f [%d]", ret); | ||
607 | return false; | ||
608 | } | ||
609 | |||
610 | retries++; | ||
611 | if (retries == 4) { | ||
612 | fc->ac.error = -ESTALE; | ||
613 | _leave(" = f [stale]"); | ||
614 | return false; | ||
615 | } | ||
616 | _debug("retry"); | ||
617 | goto retry; | ||
618 | } | ||
619 | |||
620 | /* | ||
621 | * Get an update for a server's address list. | 514 | * Get an update for a server's address list. |
622 | */ | 515 | */ |
623 | static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct afs_server *server) | 516 | static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct afs_server *server) |
diff --git a/fs/afs/server_list.c b/fs/afs/server_list.c index 8a5760aa5832..95d0761cdb34 100644 --- a/fs/afs/server_list.c +++ b/fs/afs/server_list.c | |||
@@ -118,11 +118,11 @@ bool afs_annotate_server_list(struct afs_server_list *new, | |||
118 | return false; | 118 | return false; |
119 | 119 | ||
120 | changed: | 120 | changed: |
121 | /* Maintain the same current server as before if possible. */ | 121 | /* Maintain the same preferred server as before if possible. */ |
122 | cur = old->servers[old->index].server; | 122 | cur = old->servers[old->preferred].server; |
123 | for (j = 0; j < new->nr_servers; j++) { | 123 | for (j = 0; j < new->nr_servers; j++) { |
124 | if (new->servers[j].server == cur) { | 124 | if (new->servers[j].server == cur) { |
125 | new->index = j; | 125 | new->preferred = j; |
126 | break; | 126 | break; |
127 | } | 127 | } |
128 | } | 128 | } |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 4d3e274207fb..dcd07fe99871 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -406,10 +406,11 @@ static int afs_fill_super(struct super_block *sb, | |||
406 | inode = afs_iget_pseudo_dir(sb, true); | 406 | inode = afs_iget_pseudo_dir(sb, true); |
407 | sb->s_flags |= SB_RDONLY; | 407 | sb->s_flags |= SB_RDONLY; |
408 | } else { | 408 | } else { |
409 | sprintf(sb->s_id, "%u", as->volume->vid); | 409 | sprintf(sb->s_id, "%llu", as->volume->vid); |
410 | afs_activate_volume(as->volume); | 410 | afs_activate_volume(as->volume); |
411 | fid.vid = as->volume->vid; | 411 | fid.vid = as->volume->vid; |
412 | fid.vnode = 1; | 412 | fid.vnode = 1; |
413 | fid.vnode_hi = 0; | ||
413 | fid.unique = 1; | 414 | fid.unique = 1; |
414 | inode = afs_iget(sb, params->key, &fid, NULL, NULL, NULL); | 415 | inode = afs_iget(sb, params->key, &fid, NULL, NULL, NULL); |
415 | } | 416 | } |
@@ -663,7 +664,7 @@ static void afs_destroy_inode(struct inode *inode) | |||
663 | { | 664 | { |
664 | struct afs_vnode *vnode = AFS_FS_I(inode); | 665 | struct afs_vnode *vnode = AFS_FS_I(inode); |
665 | 666 | ||
666 | _enter("%p{%x:%u}", inode, vnode->fid.vid, vnode->fid.vnode); | 667 | _enter("%p{%llx:%llu}", inode, vnode->fid.vid, vnode->fid.vnode); |
667 | 668 | ||
668 | _debug("DESTROY INODE %p", inode); | 669 | _debug("DESTROY INODE %p", inode); |
669 | 670 | ||
diff --git a/fs/afs/vl_list.c b/fs/afs/vl_list.c new file mode 100644 index 000000000000..b4f1a84519b9 --- /dev/null +++ b/fs/afs/vl_list.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* AFS vlserver list management. | ||
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 License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include "internal.h" | ||
15 | |||
16 | struct afs_vlserver *afs_alloc_vlserver(const char *name, size_t name_len, | ||
17 | unsigned short port) | ||
18 | { | ||
19 | struct afs_vlserver *vlserver; | ||
20 | |||
21 | vlserver = kzalloc(struct_size(vlserver, name, name_len + 1), | ||
22 | GFP_KERNEL); | ||
23 | if (vlserver) { | ||
24 | atomic_set(&vlserver->usage, 1); | ||
25 | rwlock_init(&vlserver->lock); | ||
26 | init_waitqueue_head(&vlserver->probe_wq); | ||
27 | spin_lock_init(&vlserver->probe_lock); | ||
28 | vlserver->name_len = name_len; | ||
29 | vlserver->port = port; | ||
30 | memcpy(vlserver->name, name, name_len); | ||
31 | } | ||
32 | return vlserver; | ||
33 | } | ||
34 | |||
35 | static void afs_vlserver_rcu(struct rcu_head *rcu) | ||
36 | { | ||
37 | struct afs_vlserver *vlserver = container_of(rcu, struct afs_vlserver, rcu); | ||
38 | |||
39 | afs_put_addrlist(rcu_access_pointer(vlserver->addresses)); | ||
40 | kfree_rcu(vlserver, rcu); | ||
41 | } | ||
42 | |||
43 | void afs_put_vlserver(struct afs_net *net, struct afs_vlserver *vlserver) | ||
44 | { | ||
45 | if (vlserver) { | ||
46 | unsigned int u = atomic_dec_return(&vlserver->usage); | ||
47 | //_debug("VL PUT %p{%u}", vlserver, u); | ||
48 | |||
49 | if (u == 0) | ||
50 | call_rcu(&vlserver->rcu, afs_vlserver_rcu); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | struct afs_vlserver_list *afs_alloc_vlserver_list(unsigned int nr_servers) | ||
55 | { | ||
56 | struct afs_vlserver_list *vllist; | ||
57 | |||
58 | vllist = kzalloc(struct_size(vllist, servers, nr_servers), GFP_KERNEL); | ||
59 | if (vllist) { | ||
60 | atomic_set(&vllist->usage, 1); | ||
61 | rwlock_init(&vllist->lock); | ||
62 | } | ||
63 | |||
64 | return vllist; | ||
65 | } | ||
66 | |||
67 | void afs_put_vlserverlist(struct afs_net *net, struct afs_vlserver_list *vllist) | ||
68 | { | ||
69 | if (vllist) { | ||
70 | unsigned int u = atomic_dec_return(&vllist->usage); | ||
71 | |||
72 | //_debug("VLLS PUT %p{%u}", vllist, u); | ||
73 | if (u == 0) { | ||
74 | int i; | ||
75 | |||
76 | for (i = 0; i < vllist->nr_servers; i++) { | ||
77 | afs_put_vlserver(net, vllist->servers[i].server); | ||
78 | } | ||
79 | kfree_rcu(vllist, rcu); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static u16 afs_extract_le16(const u8 **_b) | ||
85 | { | ||
86 | u16 val; | ||
87 | |||
88 | val = (u16)*(*_b)++ << 0; | ||
89 | val |= (u16)*(*_b)++ << 8; | ||
90 | return val; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * Build a VL server address list from a DNS queried server list. | ||
95 | */ | ||
96 | static struct afs_addr_list *afs_extract_vl_addrs(const u8 **_b, const u8 *end, | ||
97 | u8 nr_addrs, u16 port) | ||
98 | { | ||
99 | struct afs_addr_list *alist; | ||
100 | const u8 *b = *_b; | ||
101 | int ret = -EINVAL; | ||
102 | |||
103 | alist = afs_alloc_addrlist(nr_addrs, VL_SERVICE, port); | ||
104 | if (!alist) | ||
105 | return ERR_PTR(-ENOMEM); | ||
106 | if (nr_addrs == 0) | ||
107 | return alist; | ||
108 | |||
109 | for (; nr_addrs > 0 && end - b >= nr_addrs; nr_addrs--) { | ||
110 | struct dns_server_list_v1_address hdr; | ||
111 | __be32 x[4]; | ||
112 | |||
113 | hdr.address_type = *b++; | ||
114 | |||
115 | switch (hdr.address_type) { | ||
116 | case DNS_ADDRESS_IS_IPV4: | ||
117 | if (end - b < 4) { | ||
118 | _leave(" = -EINVAL [short inet]"); | ||
119 | goto error; | ||
120 | } | ||
121 | memcpy(x, b, 4); | ||
122 | afs_merge_fs_addr4(alist, x[0], port); | ||
123 | b += 4; | ||
124 | break; | ||
125 | |||
126 | case DNS_ADDRESS_IS_IPV6: | ||
127 | if (end - b < 16) { | ||
128 | _leave(" = -EINVAL [short inet6]"); | ||
129 | goto error; | ||
130 | } | ||
131 | memcpy(x, b, 16); | ||
132 | afs_merge_fs_addr6(alist, x, port); | ||
133 | b += 16; | ||
134 | break; | ||
135 | |||
136 | default: | ||
137 | _leave(" = -EADDRNOTAVAIL [unknown af %u]", | ||
138 | hdr.address_type); | ||
139 | ret = -EADDRNOTAVAIL; | ||
140 | goto error; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | /* Start with IPv6 if available. */ | ||
145 | if (alist->nr_ipv4 < alist->nr_addrs) | ||
146 | alist->preferred = alist->nr_ipv4; | ||
147 | |||
148 | *_b = b; | ||
149 | return alist; | ||
150 | |||
151 | error: | ||
152 | *_b = b; | ||
153 | afs_put_addrlist(alist); | ||
154 | return ERR_PTR(ret); | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * Build a VL server list from a DNS queried server list. | ||
159 | */ | ||
160 | struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *cell, | ||
161 | const void *buffer, | ||
162 | size_t buffer_size) | ||
163 | { | ||
164 | const struct dns_server_list_v1_header *hdr = buffer; | ||
165 | struct dns_server_list_v1_server bs; | ||
166 | struct afs_vlserver_list *vllist, *previous; | ||
167 | struct afs_addr_list *addrs; | ||
168 | struct afs_vlserver *server; | ||
169 | const u8 *b = buffer, *end = buffer + buffer_size; | ||
170 | int ret = -ENOMEM, nr_servers, i, j; | ||
171 | |||
172 | _enter(""); | ||
173 | |||
174 | /* Check that it's a server list, v1 */ | ||
175 | if (end - b < sizeof(*hdr) || | ||
176 | hdr->hdr.content != DNS_PAYLOAD_IS_SERVER_LIST || | ||
177 | hdr->hdr.version != 1) { | ||
178 | pr_notice("kAFS: Got DNS record [%u,%u] len %zu\n", | ||
179 | hdr->hdr.content, hdr->hdr.version, end - b); | ||
180 | ret = -EDESTADDRREQ; | ||
181 | goto dump; | ||
182 | } | ||
183 | |||
184 | nr_servers = hdr->nr_servers; | ||
185 | |||
186 | vllist = afs_alloc_vlserver_list(nr_servers); | ||
187 | if (!vllist) | ||
188 | return ERR_PTR(-ENOMEM); | ||
189 | |||
190 | vllist->source = (hdr->source < NR__dns_record_source) ? | ||
191 | hdr->source : NR__dns_record_source; | ||
192 | vllist->status = (hdr->status < NR__dns_lookup_status) ? | ||
193 | hdr->status : NR__dns_lookup_status; | ||
194 | |||
195 | read_lock(&cell->vl_servers_lock); | ||
196 | previous = afs_get_vlserverlist( | ||
197 | rcu_dereference_protected(cell->vl_servers, | ||
198 | lockdep_is_held(&cell->vl_servers_lock))); | ||
199 | read_unlock(&cell->vl_servers_lock); | ||
200 | |||
201 | b += sizeof(*hdr); | ||
202 | while (end - b >= sizeof(bs)) { | ||
203 | bs.name_len = afs_extract_le16(&b); | ||
204 | bs.priority = afs_extract_le16(&b); | ||
205 | bs.weight = afs_extract_le16(&b); | ||
206 | bs.port = afs_extract_le16(&b); | ||
207 | bs.source = *b++; | ||
208 | bs.status = *b++; | ||
209 | bs.protocol = *b++; | ||
210 | bs.nr_addrs = *b++; | ||
211 | |||
212 | _debug("extract %u %u %u %u %u %u %*.*s", | ||
213 | bs.name_len, bs.priority, bs.weight, | ||
214 | bs.port, bs.protocol, bs.nr_addrs, | ||
215 | bs.name_len, bs.name_len, b); | ||
216 | |||
217 | if (end - b < bs.name_len) | ||
218 | break; | ||
219 | |||
220 | ret = -EPROTONOSUPPORT; | ||
221 | if (bs.protocol == DNS_SERVER_PROTOCOL_UNSPECIFIED) { | ||
222 | bs.protocol = DNS_SERVER_PROTOCOL_UDP; | ||
223 | } else if (bs.protocol != DNS_SERVER_PROTOCOL_UDP) { | ||
224 | _leave(" = [proto %u]", bs.protocol); | ||
225 | goto error; | ||
226 | } | ||
227 | |||
228 | if (bs.port == 0) | ||
229 | bs.port = AFS_VL_PORT; | ||
230 | if (bs.source > NR__dns_record_source) | ||
231 | bs.source = NR__dns_record_source; | ||
232 | if (bs.status > NR__dns_lookup_status) | ||
233 | bs.status = NR__dns_lookup_status; | ||
234 | |||
235 | server = NULL; | ||
236 | if (previous) { | ||
237 | /* See if we can update an old server record */ | ||
238 | for (i = 0; i < previous->nr_servers; i++) { | ||
239 | struct afs_vlserver *p = previous->servers[i].server; | ||
240 | |||
241 | if (p->name_len == bs.name_len && | ||
242 | p->port == bs.port && | ||
243 | strncasecmp(b, p->name, bs.name_len) == 0) { | ||
244 | server = afs_get_vlserver(p); | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
250 | if (!server) { | ||
251 | ret = -ENOMEM; | ||
252 | server = afs_alloc_vlserver(b, bs.name_len, bs.port); | ||
253 | if (!server) | ||
254 | goto error; | ||
255 | } | ||
256 | |||
257 | b += bs.name_len; | ||
258 | |||
259 | /* Extract the addresses - note that we can't skip this as we | ||
260 | * have to advance the payload pointer. | ||
261 | */ | ||
262 | addrs = afs_extract_vl_addrs(&b, end, bs.nr_addrs, bs.port); | ||
263 | if (IS_ERR(addrs)) { | ||
264 | ret = PTR_ERR(addrs); | ||
265 | goto error_2; | ||
266 | } | ||
267 | |||
268 | if (vllist->nr_servers >= nr_servers) { | ||
269 | _debug("skip %u >= %u", vllist->nr_servers, nr_servers); | ||
270 | afs_put_addrlist(addrs); | ||
271 | afs_put_vlserver(cell->net, server); | ||
272 | continue; | ||
273 | } | ||
274 | |||
275 | addrs->source = bs.source; | ||
276 | addrs->status = bs.status; | ||
277 | |||
278 | if (addrs->nr_addrs == 0) { | ||
279 | afs_put_addrlist(addrs); | ||
280 | if (!rcu_access_pointer(server->addresses)) { | ||
281 | afs_put_vlserver(cell->net, server); | ||
282 | continue; | ||
283 | } | ||
284 | } else { | ||
285 | struct afs_addr_list *old = addrs; | ||
286 | |||
287 | write_lock(&server->lock); | ||
288 | rcu_swap_protected(server->addresses, old, | ||
289 | lockdep_is_held(&server->lock)); | ||
290 | write_unlock(&server->lock); | ||
291 | afs_put_addrlist(old); | ||
292 | } | ||
293 | |||
294 | |||
295 | /* TODO: Might want to check for duplicates */ | ||
296 | |||
297 | /* Insertion-sort by priority and weight */ | ||
298 | for (j = 0; j < vllist->nr_servers; j++) { | ||
299 | if (bs.priority < vllist->servers[j].priority) | ||
300 | break; /* Lower preferable */ | ||
301 | if (bs.priority == vllist->servers[j].priority && | ||
302 | bs.weight > vllist->servers[j].weight) | ||
303 | break; /* Higher preferable */ | ||
304 | } | ||
305 | |||
306 | if (j < vllist->nr_servers) { | ||
307 | memmove(vllist->servers + j + 1, | ||
308 | vllist->servers + j, | ||
309 | (vllist->nr_servers - j) * sizeof(struct afs_vlserver_entry)); | ||
310 | } | ||
311 | |||
312 | clear_bit(AFS_VLSERVER_FL_PROBED, &server->flags); | ||
313 | |||
314 | vllist->servers[j].priority = bs.priority; | ||
315 | vllist->servers[j].weight = bs.weight; | ||
316 | vllist->servers[j].server = server; | ||
317 | vllist->nr_servers++; | ||
318 | } | ||
319 | |||
320 | if (b != end) { | ||
321 | _debug("parse error %zd", b - end); | ||
322 | goto error; | ||
323 | } | ||
324 | |||
325 | afs_put_vlserverlist(cell->net, previous); | ||
326 | _leave(" = ok [%u]", vllist->nr_servers); | ||
327 | return vllist; | ||
328 | |||
329 | error_2: | ||
330 | afs_put_vlserver(cell->net, server); | ||
331 | error: | ||
332 | afs_put_vlserverlist(cell->net, vllist); | ||
333 | afs_put_vlserverlist(cell->net, previous); | ||
334 | dump: | ||
335 | if (ret != -ENOMEM) { | ||
336 | printk(KERN_DEBUG "DNS: at %zu\n", (const void *)b - buffer); | ||
337 | print_hex_dump_bytes("DNS: ", DUMP_PREFIX_NONE, buffer, buffer_size); | ||
338 | } | ||
339 | return ERR_PTR(ret); | ||
340 | } | ||
diff --git a/fs/afs/vl_probe.c b/fs/afs/vl_probe.c new file mode 100644 index 000000000000..c0f616bd70cb --- /dev/null +++ b/fs/afs/vl_probe.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /* AFS vlserver probing | ||
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 | #include <linux/sched.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include "afs_fs.h" | ||
15 | #include "internal.h" | ||
16 | #include "protocol_yfs.h" | ||
17 | |||
18 | static bool afs_vl_probe_done(struct afs_vlserver *server) | ||
19 | { | ||
20 | if (!atomic_dec_and_test(&server->probe_outstanding)) | ||
21 | return false; | ||
22 | |||
23 | wake_up_var(&server->probe_outstanding); | ||
24 | clear_bit_unlock(AFS_VLSERVER_FL_PROBING, &server->flags); | ||
25 | wake_up_bit(&server->flags, AFS_VLSERVER_FL_PROBING); | ||
26 | return true; | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Process the result of probing a vlserver. This is called after successful | ||
31 | * or failed delivery of an VL.GetCapabilities operation. | ||
32 | */ | ||
33 | void afs_vlserver_probe_result(struct afs_call *call) | ||
34 | { | ||
35 | struct afs_addr_list *alist = call->alist; | ||
36 | struct afs_vlserver *server = call->reply[0]; | ||
37 | unsigned int server_index = (long)call->reply[1]; | ||
38 | unsigned int index = call->addr_ix; | ||
39 | unsigned int rtt = UINT_MAX; | ||
40 | bool have_result = false; | ||
41 | u64 _rtt; | ||
42 | int ret = call->error; | ||
43 | |||
44 | _enter("%s,%u,%u,%d,%d", server->name, server_index, index, ret, call->abort_code); | ||
45 | |||
46 | spin_lock(&server->probe_lock); | ||
47 | |||
48 | switch (ret) { | ||
49 | case 0: | ||
50 | server->probe.error = 0; | ||
51 | goto responded; | ||
52 | case -ECONNABORTED: | ||
53 | if (!server->probe.responded) { | ||
54 | server->probe.abort_code = call->abort_code; | ||
55 | server->probe.error = ret; | ||
56 | } | ||
57 | goto responded; | ||
58 | case -ENOMEM: | ||
59 | case -ENONET: | ||
60 | server->probe.local_failure = true; | ||
61 | afs_io_error(call, afs_io_error_vl_probe_fail); | ||
62 | goto out; | ||
63 | case -ECONNRESET: /* Responded, but call expired. */ | ||
64 | case -ENETUNREACH: | ||
65 | case -EHOSTUNREACH: | ||
66 | case -ECONNREFUSED: | ||
67 | case -ETIMEDOUT: | ||
68 | case -ETIME: | ||
69 | default: | ||
70 | clear_bit(index, &alist->responded); | ||
71 | set_bit(index, &alist->failed); | ||
72 | if (!server->probe.responded && | ||
73 | (server->probe.error == 0 || | ||
74 | server->probe.error == -ETIMEDOUT || | ||
75 | server->probe.error == -ETIME)) | ||
76 | server->probe.error = ret; | ||
77 | afs_io_error(call, afs_io_error_vl_probe_fail); | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | responded: | ||
82 | set_bit(index, &alist->responded); | ||
83 | clear_bit(index, &alist->failed); | ||
84 | |||
85 | if (call->service_id == YFS_VL_SERVICE) { | ||
86 | server->probe.is_yfs = true; | ||
87 | set_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); | ||
88 | alist->addrs[index].srx_service = call->service_id; | ||
89 | } else { | ||
90 | server->probe.not_yfs = true; | ||
91 | if (!server->probe.is_yfs) { | ||
92 | clear_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); | ||
93 | alist->addrs[index].srx_service = call->service_id; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /* Get the RTT and scale it to fit into a 32-bit value that represents | ||
98 | * over a minute of time so that we can access it with one instruction | ||
99 | * on a 32-bit system. | ||
100 | */ | ||
101 | _rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall); | ||
102 | _rtt /= 64; | ||
103 | rtt = (_rtt > UINT_MAX) ? UINT_MAX : _rtt; | ||
104 | if (rtt < server->probe.rtt) { | ||
105 | server->probe.rtt = rtt; | ||
106 | alist->preferred = index; | ||
107 | have_result = true; | ||
108 | } | ||
109 | |||
110 | smp_wmb(); /* Set rtt before responded. */ | ||
111 | server->probe.responded = true; | ||
112 | set_bit(AFS_VLSERVER_FL_PROBED, &server->flags); | ||
113 | out: | ||
114 | spin_unlock(&server->probe_lock); | ||
115 | |||
116 | _debug("probe [%u][%u] %pISpc rtt=%u ret=%d", | ||
117 | server_index, index, &alist->addrs[index].transport, | ||
118 | (unsigned int)rtt, ret); | ||
119 | |||
120 | have_result |= afs_vl_probe_done(server); | ||
121 | if (have_result) { | ||
122 | server->probe.have_result = true; | ||
123 | wake_up_var(&server->probe.have_result); | ||
124 | wake_up_all(&server->probe_wq); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Probe all of a vlserver's addresses to find out the best route and to | ||
130 | * query its capabilities. | ||
131 | */ | ||
132 | static int afs_do_probe_vlserver(struct afs_net *net, | ||
133 | struct afs_vlserver *server, | ||
134 | struct key *key, | ||
135 | unsigned int server_index) | ||
136 | { | ||
137 | struct afs_addr_cursor ac = { | ||
138 | .index = 0, | ||
139 | }; | ||
140 | int ret; | ||
141 | |||
142 | _enter("%s", server->name); | ||
143 | |||
144 | read_lock(&server->lock); | ||
145 | ac.alist = rcu_dereference_protected(server->addresses, | ||
146 | lockdep_is_held(&server->lock)); | ||
147 | read_unlock(&server->lock); | ||
148 | |||
149 | atomic_set(&server->probe_outstanding, ac.alist->nr_addrs); | ||
150 | memset(&server->probe, 0, sizeof(server->probe)); | ||
151 | server->probe.rtt = UINT_MAX; | ||
152 | |||
153 | for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) { | ||
154 | ret = afs_vl_get_capabilities(net, &ac, key, server, | ||
155 | server_index, true); | ||
156 | if (ret != -EINPROGRESS) { | ||
157 | afs_vl_probe_done(server); | ||
158 | return ret; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Send off probes to all unprobed servers. | ||
167 | */ | ||
168 | int afs_send_vl_probes(struct afs_net *net, struct key *key, | ||
169 | struct afs_vlserver_list *vllist) | ||
170 | { | ||
171 | struct afs_vlserver *server; | ||
172 | int i, ret; | ||
173 | |||
174 | for (i = 0; i < vllist->nr_servers; i++) { | ||
175 | server = vllist->servers[i].server; | ||
176 | if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags)) | ||
177 | continue; | ||
178 | |||
179 | if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags)) { | ||
180 | ret = afs_do_probe_vlserver(net, server, key, i); | ||
181 | if (ret) | ||
182 | return ret; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Wait for the first as-yet untried server to respond. | ||
191 | */ | ||
192 | int afs_wait_for_vl_probes(struct afs_vlserver_list *vllist, | ||
193 | unsigned long untried) | ||
194 | { | ||
195 | struct wait_queue_entry *waits; | ||
196 | struct afs_vlserver *server; | ||
197 | unsigned int rtt = UINT_MAX; | ||
198 | bool have_responders = false; | ||
199 | int pref = -1, i; | ||
200 | |||
201 | _enter("%u,%lx", vllist->nr_servers, untried); | ||
202 | |||
203 | /* Only wait for servers that have a probe outstanding. */ | ||
204 | for (i = 0; i < vllist->nr_servers; i++) { | ||
205 | if (test_bit(i, &untried)) { | ||
206 | server = vllist->servers[i].server; | ||
207 | if (!test_bit(AFS_VLSERVER_FL_PROBING, &server->flags)) | ||
208 | __clear_bit(i, &untried); | ||
209 | if (server->probe.responded) | ||
210 | have_responders = true; | ||
211 | } | ||
212 | } | ||
213 | if (have_responders || !untried) | ||
214 | return 0; | ||
215 | |||
216 | waits = kmalloc(array_size(vllist->nr_servers, sizeof(*waits)), GFP_KERNEL); | ||
217 | if (!waits) | ||
218 | return -ENOMEM; | ||
219 | |||
220 | for (i = 0; i < vllist->nr_servers; i++) { | ||
221 | if (test_bit(i, &untried)) { | ||
222 | server = vllist->servers[i].server; | ||
223 | init_waitqueue_entry(&waits[i], current); | ||
224 | add_wait_queue(&server->probe_wq, &waits[i]); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | for (;;) { | ||
229 | bool still_probing = false; | ||
230 | |||
231 | set_current_state(TASK_INTERRUPTIBLE); | ||
232 | for (i = 0; i < vllist->nr_servers; i++) { | ||
233 | if (test_bit(i, &untried)) { | ||
234 | server = vllist->servers[i].server; | ||
235 | if (server->probe.responded) | ||
236 | goto stop; | ||
237 | if (test_bit(AFS_VLSERVER_FL_PROBING, &server->flags)) | ||
238 | still_probing = true; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | if (!still_probing || unlikely(signal_pending(current))) | ||
243 | goto stop; | ||
244 | schedule(); | ||
245 | } | ||
246 | |||
247 | stop: | ||
248 | set_current_state(TASK_RUNNING); | ||
249 | |||
250 | for (i = 0; i < vllist->nr_servers; i++) { | ||
251 | if (test_bit(i, &untried)) { | ||
252 | server = vllist->servers[i].server; | ||
253 | if (server->probe.responded && | ||
254 | server->probe.rtt < rtt) { | ||
255 | pref = i; | ||
256 | rtt = server->probe.rtt; | ||
257 | } | ||
258 | |||
259 | remove_wait_queue(&server->probe_wq, &waits[i]); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | kfree(waits); | ||
264 | |||
265 | if (pref == -1 && signal_pending(current)) | ||
266 | return -ERESTARTSYS; | ||
267 | |||
268 | if (pref >= 0) | ||
269 | vllist->preferred = pref; | ||
270 | |||
271 | _leave(" = 0 [%u]", pref); | ||
272 | return 0; | ||
273 | } | ||
diff --git a/fs/afs/vl_rotate.c b/fs/afs/vl_rotate.c new file mode 100644 index 000000000000..b64a284b99d2 --- /dev/null +++ b/fs/afs/vl_rotate.c | |||
@@ -0,0 +1,355 @@ | |||
1 | /* Handle vlserver selection and rotation. | ||
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 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/sched/signal.h> | ||
15 | #include "internal.h" | ||
16 | #include "afs_vl.h" | ||
17 | |||
18 | /* | ||
19 | * Begin an operation on a volume location server. | ||
20 | */ | ||
21 | bool afs_begin_vlserver_operation(struct afs_vl_cursor *vc, struct afs_cell *cell, | ||
22 | struct key *key) | ||
23 | { | ||
24 | memset(vc, 0, sizeof(*vc)); | ||
25 | vc->cell = cell; | ||
26 | vc->key = key; | ||
27 | vc->error = -EDESTADDRREQ; | ||
28 | vc->ac.error = SHRT_MAX; | ||
29 | |||
30 | if (signal_pending(current)) { | ||
31 | vc->error = -EINTR; | ||
32 | vc->flags |= AFS_VL_CURSOR_STOP; | ||
33 | return false; | ||
34 | } | ||
35 | |||
36 | return true; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Begin iteration through a server list, starting with the last used server if | ||
41 | * possible, or the last recorded good server if not. | ||
42 | */ | ||
43 | static bool afs_start_vl_iteration(struct afs_vl_cursor *vc) | ||
44 | { | ||
45 | struct afs_cell *cell = vc->cell; | ||
46 | |||
47 | if (wait_on_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET, | ||
48 | TASK_INTERRUPTIBLE)) { | ||
49 | vc->error = -ERESTARTSYS; | ||
50 | return false; | ||
51 | } | ||
52 | |||
53 | read_lock(&cell->vl_servers_lock); | ||
54 | vc->server_list = afs_get_vlserverlist( | ||
55 | rcu_dereference_protected(cell->vl_servers, | ||
56 | lockdep_is_held(&cell->vl_servers_lock))); | ||
57 | read_unlock(&cell->vl_servers_lock); | ||
58 | if (!vc->server_list || !vc->server_list->nr_servers) | ||
59 | return false; | ||
60 | |||
61 | vc->untried = (1UL << vc->server_list->nr_servers) - 1; | ||
62 | vc->index = -1; | ||
63 | return true; | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Select the vlserver to use. May be called multiple times to rotate | ||
68 | * through the vlservers. | ||
69 | */ | ||
70 | bool afs_select_vlserver(struct afs_vl_cursor *vc) | ||
71 | { | ||
72 | struct afs_addr_list *alist; | ||
73 | struct afs_vlserver *vlserver; | ||
74 | u32 rtt; | ||
75 | int error = vc->ac.error, abort_code, i; | ||
76 | |||
77 | _enter("%lx[%d],%lx[%d],%d,%d", | ||
78 | vc->untried, vc->index, | ||
79 | vc->ac.tried, vc->ac.index, | ||
80 | error, vc->ac.abort_code); | ||
81 | |||
82 | if (vc->flags & AFS_VL_CURSOR_STOP) { | ||
83 | _leave(" = f [stopped]"); | ||
84 | return false; | ||
85 | } | ||
86 | |||
87 | vc->nr_iterations++; | ||
88 | |||
89 | /* Evaluate the result of the previous operation, if there was one. */ | ||
90 | switch (error) { | ||
91 | case SHRT_MAX: | ||
92 | goto start; | ||
93 | |||
94 | default: | ||
95 | case 0: | ||
96 | /* Success or local failure. Stop. */ | ||
97 | vc->error = error; | ||
98 | vc->flags |= AFS_VL_CURSOR_STOP; | ||
99 | _leave(" = f [okay/local %d]", vc->ac.error); | ||
100 | return false; | ||
101 | |||
102 | case -ECONNABORTED: | ||
103 | /* The far side rejected the operation on some grounds. This | ||
104 | * might involve the server being busy or the volume having been moved. | ||
105 | */ | ||
106 | switch (vc->ac.abort_code) { | ||
107 | case AFSVL_IO: | ||
108 | case AFSVL_BADVOLOPER: | ||
109 | case AFSVL_NOMEM: | ||
110 | /* The server went weird. */ | ||
111 | vc->error = -EREMOTEIO; | ||
112 | //write_lock(&vc->cell->vl_servers_lock); | ||
113 | //vc->server_list->weird_mask |= 1 << vc->index; | ||
114 | //write_unlock(&vc->cell->vl_servers_lock); | ||
115 | goto next_server; | ||
116 | |||
117 | default: | ||
118 | vc->error = afs_abort_to_error(vc->ac.abort_code); | ||
119 | goto failed; | ||
120 | } | ||
121 | |||
122 | case -ENETUNREACH: | ||
123 | case -EHOSTUNREACH: | ||
124 | case -ECONNREFUSED: | ||
125 | case -ETIMEDOUT: | ||
126 | case -ETIME: | ||
127 | _debug("no conn %d", error); | ||
128 | vc->error = error; | ||
129 | goto iterate_address; | ||
130 | |||
131 | case -ECONNRESET: | ||
132 | _debug("call reset"); | ||
133 | vc->error = error; | ||
134 | vc->flags |= AFS_VL_CURSOR_RETRY; | ||
135 | goto next_server; | ||
136 | } | ||
137 | |||
138 | restart_from_beginning: | ||
139 | _debug("restart"); | ||
140 | afs_end_cursor(&vc->ac); | ||
141 | afs_put_vlserverlist(vc->cell->net, vc->server_list); | ||
142 | vc->server_list = NULL; | ||
143 | if (vc->flags & AFS_VL_CURSOR_RETRIED) | ||
144 | goto failed; | ||
145 | vc->flags |= AFS_VL_CURSOR_RETRIED; | ||
146 | start: | ||
147 | _debug("start"); | ||
148 | |||
149 | if (!afs_start_vl_iteration(vc)) | ||
150 | goto failed; | ||
151 | |||
152 | error = afs_send_vl_probes(vc->cell->net, vc->key, vc->server_list); | ||
153 | if (error < 0) | ||
154 | goto failed_set_error; | ||
155 | |||
156 | pick_server: | ||
157 | _debug("pick [%lx]", vc->untried); | ||
158 | |||
159 | error = afs_wait_for_vl_probes(vc->server_list, vc->untried); | ||
160 | if (error < 0) | ||
161 | goto failed_set_error; | ||
162 | |||
163 | /* Pick the untried server with the lowest RTT. */ | ||
164 | vc->index = vc->server_list->preferred; | ||
165 | if (test_bit(vc->index, &vc->untried)) | ||
166 | goto selected_server; | ||
167 | |||
168 | vc->index = -1; | ||
169 | rtt = U32_MAX; | ||
170 | for (i = 0; i < vc->server_list->nr_servers; i++) { | ||
171 | struct afs_vlserver *s = vc->server_list->servers[i].server; | ||
172 | |||
173 | if (!test_bit(i, &vc->untried) || !s->probe.responded) | ||
174 | continue; | ||
175 | if (s->probe.rtt < rtt) { | ||
176 | vc->index = i; | ||
177 | rtt = s->probe.rtt; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | if (vc->index == -1) | ||
182 | goto no_more_servers; | ||
183 | |||
184 | selected_server: | ||
185 | _debug("use %d", vc->index); | ||
186 | __clear_bit(vc->index, &vc->untried); | ||
187 | |||
188 | /* We're starting on a different vlserver from the list. We need to | ||
189 | * check it, find its address list and probe its capabilities before we | ||
190 | * use it. | ||
191 | */ | ||
192 | ASSERTCMP(vc->ac.alist, ==, NULL); | ||
193 | vlserver = vc->server_list->servers[vc->index].server; | ||
194 | vc->server = vlserver; | ||
195 | |||
196 | _debug("USING VLSERVER: %s", vlserver->name); | ||
197 | |||
198 | read_lock(&vlserver->lock); | ||
199 | alist = rcu_dereference_protected(vlserver->addresses, | ||
200 | lockdep_is_held(&vlserver->lock)); | ||
201 | afs_get_addrlist(alist); | ||
202 | read_unlock(&vlserver->lock); | ||
203 | |||
204 | memset(&vc->ac, 0, sizeof(vc->ac)); | ||
205 | |||
206 | if (!vc->ac.alist) | ||
207 | vc->ac.alist = alist; | ||
208 | else | ||
209 | afs_put_addrlist(alist); | ||
210 | |||
211 | vc->ac.index = -1; | ||
212 | |||
213 | iterate_address: | ||
214 | ASSERT(vc->ac.alist); | ||
215 | /* Iterate over the current server's address list to try and find an | ||
216 | * address on which it will respond to us. | ||
217 | */ | ||
218 | if (!afs_iterate_addresses(&vc->ac)) | ||
219 | goto next_server; | ||
220 | |||
221 | _debug("VL address %d/%d", vc->ac.index, vc->ac.alist->nr_addrs); | ||
222 | |||
223 | _leave(" = t %pISpc", &vc->ac.alist->addrs[vc->ac.index].transport); | ||
224 | return true; | ||
225 | |||
226 | next_server: | ||
227 | _debug("next"); | ||
228 | afs_end_cursor(&vc->ac); | ||
229 | goto pick_server; | ||
230 | |||
231 | no_more_servers: | ||
232 | /* That's all the servers poked to no good effect. Try again if some | ||
233 | * of them were busy. | ||
234 | */ | ||
235 | if (vc->flags & AFS_VL_CURSOR_RETRY) | ||
236 | goto restart_from_beginning; | ||
237 | |||
238 | abort_code = 0; | ||
239 | error = -EDESTADDRREQ; | ||
240 | for (i = 0; i < vc->server_list->nr_servers; i++) { | ||
241 | struct afs_vlserver *s = vc->server_list->servers[i].server; | ||
242 | int probe_error = READ_ONCE(s->probe.error); | ||
243 | |||
244 | switch (probe_error) { | ||
245 | case 0: | ||
246 | continue; | ||
247 | default: | ||
248 | if (error == -ETIMEDOUT || | ||
249 | error == -ETIME) | ||
250 | continue; | ||
251 | case -ETIMEDOUT: | ||
252 | case -ETIME: | ||
253 | if (error == -ENOMEM || | ||
254 | error == -ENONET) | ||
255 | continue; | ||
256 | case -ENOMEM: | ||
257 | case -ENONET: | ||
258 | if (error == -ENETUNREACH) | ||
259 | continue; | ||
260 | case -ENETUNREACH: | ||
261 | if (error == -EHOSTUNREACH) | ||
262 | continue; | ||
263 | case -EHOSTUNREACH: | ||
264 | if (error == -ECONNREFUSED) | ||
265 | continue; | ||
266 | case -ECONNREFUSED: | ||
267 | if (error == -ECONNRESET) | ||
268 | continue; | ||
269 | case -ECONNRESET: /* Responded, but call expired. */ | ||
270 | if (error == -ECONNABORTED) | ||
271 | continue; | ||
272 | case -ECONNABORTED: | ||
273 | abort_code = s->probe.abort_code; | ||
274 | error = probe_error; | ||
275 | continue; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | if (error == -ECONNABORTED) | ||
280 | error = afs_abort_to_error(abort_code); | ||
281 | |||
282 | failed_set_error: | ||
283 | vc->error = error; | ||
284 | failed: | ||
285 | vc->flags |= AFS_VL_CURSOR_STOP; | ||
286 | afs_end_cursor(&vc->ac); | ||
287 | _leave(" = f [failed %d]", vc->error); | ||
288 | return false; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Dump cursor state in the case of the error being EDESTADDRREQ. | ||
293 | */ | ||
294 | static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc) | ||
295 | { | ||
296 | static int count; | ||
297 | int i; | ||
298 | |||
299 | if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3) | ||
300 | return; | ||
301 | count++; | ||
302 | |||
303 | rcu_read_lock(); | ||
304 | pr_notice("EDESTADDR occurred\n"); | ||
305 | pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd\n", | ||
306 | vc->untried, vc->index, vc->nr_iterations, vc->flags, vc->error); | ||
307 | |||
308 | if (vc->server_list) { | ||
309 | const struct afs_vlserver_list *sl = vc->server_list; | ||
310 | pr_notice("VC: SL nr=%u ix=%u\n", | ||
311 | sl->nr_servers, sl->index); | ||
312 | for (i = 0; i < sl->nr_servers; i++) { | ||
313 | const struct afs_vlserver *s = sl->servers[i].server; | ||
314 | pr_notice("VC: server %s+%hu fl=%lx E=%hd\n", | ||
315 | s->name, s->port, s->flags, s->probe.error); | ||
316 | if (s->addresses) { | ||
317 | const struct afs_addr_list *a = | ||
318 | rcu_dereference(s->addresses); | ||
319 | pr_notice("VC: - nr=%u/%u/%u pf=%u\n", | ||
320 | a->nr_ipv4, a->nr_addrs, a->max_addrs, | ||
321 | a->preferred); | ||
322 | pr_notice("VC: - pr=%lx R=%lx F=%lx\n", | ||
323 | a->probed, a->responded, a->failed); | ||
324 | if (a == vc->ac.alist) | ||
325 | pr_notice("VC: - current\n"); | ||
326 | } | ||
327 | } | ||
328 | } | ||
329 | |||
330 | pr_notice("AC: t=%lx ax=%u ac=%d er=%d r=%u ni=%u\n", | ||
331 | vc->ac.tried, vc->ac.index, vc->ac.abort_code, vc->ac.error, | ||
332 | vc->ac.responded, vc->ac.nr_iterations); | ||
333 | rcu_read_unlock(); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * Tidy up a volume location server cursor and unlock the vnode. | ||
338 | */ | ||
339 | int afs_end_vlserver_operation(struct afs_vl_cursor *vc) | ||
340 | { | ||
341 | struct afs_net *net = vc->cell->net; | ||
342 | |||
343 | if (vc->error == -EDESTADDRREQ || | ||
344 | vc->error == -ENETUNREACH || | ||
345 | vc->error == -EHOSTUNREACH) | ||
346 | afs_vl_dump_edestaddrreq(vc); | ||
347 | |||
348 | afs_end_cursor(&vc->ac); | ||
349 | afs_put_vlserverlist(net, vc->server_list); | ||
350 | |||
351 | if (vc->error == -ECONNABORTED) | ||
352 | vc->error = afs_abort_to_error(vc->ac.abort_code); | ||
353 | |||
354 | return vc->error; | ||
355 | } | ||
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c index c3b740813fc7..c3d9e5a5f67e 100644 --- a/fs/afs/vlclient.c +++ b/fs/afs/vlclient.c | |||
@@ -128,14 +128,13 @@ static const struct afs_call_type afs_RXVLGetEntryByNameU = { | |||
128 | * Dispatch a get volume entry by name or ID operation (uuid variant). If the | 128 | * Dispatch a get volume entry by name or ID operation (uuid variant). If the |
129 | * volname is a decimal number then it's a volume ID not a volume name. | 129 | * volname is a decimal number then it's a volume ID not a volume name. |
130 | */ | 130 | */ |
131 | struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_net *net, | 131 | struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc, |
132 | struct afs_addr_cursor *ac, | ||
133 | struct key *key, | ||
134 | const char *volname, | 132 | const char *volname, |
135 | int volnamesz) | 133 | int volnamesz) |
136 | { | 134 | { |
137 | struct afs_vldb_entry *entry; | 135 | struct afs_vldb_entry *entry; |
138 | struct afs_call *call; | 136 | struct afs_call *call; |
137 | struct afs_net *net = vc->cell->net; | ||
139 | size_t reqsz, padsz; | 138 | size_t reqsz, padsz; |
140 | __be32 *bp; | 139 | __be32 *bp; |
141 | 140 | ||
@@ -155,7 +154,7 @@ struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_net *net, | |||
155 | return ERR_PTR(-ENOMEM); | 154 | return ERR_PTR(-ENOMEM); |
156 | } | 155 | } |
157 | 156 | ||
158 | call->key = key; | 157 | call->key = vc->key; |
159 | call->reply[0] = entry; | 158 | call->reply[0] = entry; |
160 | call->ret_reply0 = true; | 159 | call->ret_reply0 = true; |
161 | 160 | ||
@@ -168,7 +167,7 @@ struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_net *net, | |||
168 | memset((void *)bp + volnamesz, 0, padsz); | 167 | memset((void *)bp + volnamesz, 0, padsz); |
169 | 168 | ||
170 | trace_afs_make_vl_call(call); | 169 | trace_afs_make_vl_call(call); |
171 | return (struct afs_vldb_entry *)afs_make_call(ac, call, GFP_KERNEL, false); | 170 | return (struct afs_vldb_entry *)afs_make_call(&vc->ac, call, GFP_KERNEL, false); |
172 | } | 171 | } |
173 | 172 | ||
174 | /* | 173 | /* |
@@ -187,19 +186,18 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) | |||
187 | u32 uniquifier, nentries, count; | 186 | u32 uniquifier, nentries, count; |
188 | int i, ret; | 187 | int i, ret; |
189 | 188 | ||
190 | _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); | 189 | _enter("{%u,%zu/%u}", |
190 | call->unmarshall, iov_iter_count(call->_iter), call->count); | ||
191 | 191 | ||
192 | again: | ||
193 | switch (call->unmarshall) { | 192 | switch (call->unmarshall) { |
194 | case 0: | 193 | case 0: |
195 | call->offset = 0; | 194 | afs_extract_to_buf(call, |
195 | sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32)); | ||
196 | call->unmarshall++; | 196 | call->unmarshall++; |
197 | 197 | ||
198 | /* Extract the returned uuid, uniquifier, nentries and blkaddrs size */ | 198 | /* Extract the returned uuid, uniquifier, nentries and blkaddrs size */ |
199 | case 1: | 199 | case 1: |
200 | ret = afs_extract_data(call, call->buffer, | 200 | ret = afs_extract_data(call, true); |
201 | sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32), | ||
202 | true); | ||
203 | if (ret < 0) | 201 | if (ret < 0) |
204 | return ret; | 202 | return ret; |
205 | 203 | ||
@@ -216,28 +214,28 @@ again: | |||
216 | call->reply[0] = alist; | 214 | call->reply[0] = alist; |
217 | call->count = count; | 215 | call->count = count; |
218 | call->count2 = nentries; | 216 | call->count2 = nentries; |
219 | call->offset = 0; | ||
220 | call->unmarshall++; | 217 | call->unmarshall++; |
221 | 218 | ||
219 | more_entries: | ||
220 | count = min(call->count, 4U); | ||
221 | afs_extract_to_buf(call, count * sizeof(__be32)); | ||
222 | |||
222 | /* Extract entries */ | 223 | /* Extract entries */ |
223 | case 2: | 224 | case 2: |
224 | count = min(call->count, 4U); | 225 | ret = afs_extract_data(call, call->count > 4); |
225 | ret = afs_extract_data(call, call->buffer, | ||
226 | count * sizeof(__be32), | ||
227 | call->count > 4); | ||
228 | if (ret < 0) | 226 | if (ret < 0) |
229 | return ret; | 227 | return ret; |
230 | 228 | ||
231 | alist = call->reply[0]; | 229 | alist = call->reply[0]; |
232 | bp = call->buffer; | 230 | bp = call->buffer; |
231 | count = min(call->count, 4U); | ||
233 | for (i = 0; i < count; i++) | 232 | for (i = 0; i < count; i++) |
234 | if (alist->nr_addrs < call->count2) | 233 | if (alist->nr_addrs < call->count2) |
235 | afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); | 234 | afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); |
236 | 235 | ||
237 | call->count -= count; | 236 | call->count -= count; |
238 | if (call->count > 0) | 237 | if (call->count > 0) |
239 | goto again; | 238 | goto more_entries; |
240 | call->offset = 0; | ||
241 | call->unmarshall++; | 239 | call->unmarshall++; |
242 | break; | 240 | break; |
243 | } | 241 | } |
@@ -267,14 +265,13 @@ static const struct afs_call_type afs_RXVLGetAddrsU = { | |||
267 | * Dispatch an operation to get the addresses for a server, where the server is | 265 | * Dispatch an operation to get the addresses for a server, where the server is |
268 | * nominated by UUID. | 266 | * nominated by UUID. |
269 | */ | 267 | */ |
270 | struct afs_addr_list *afs_vl_get_addrs_u(struct afs_net *net, | 268 | struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc, |
271 | struct afs_addr_cursor *ac, | ||
272 | struct key *key, | ||
273 | const uuid_t *uuid) | 269 | const uuid_t *uuid) |
274 | { | 270 | { |
275 | struct afs_ListAddrByAttributes__xdr *r; | 271 | struct afs_ListAddrByAttributes__xdr *r; |
276 | const struct afs_uuid *u = (const struct afs_uuid *)uuid; | 272 | const struct afs_uuid *u = (const struct afs_uuid *)uuid; |
277 | struct afs_call *call; | 273 | struct afs_call *call; |
274 | struct afs_net *net = vc->cell->net; | ||
278 | __be32 *bp; | 275 | __be32 *bp; |
279 | int i; | 276 | int i; |
280 | 277 | ||
@@ -286,7 +283,7 @@ struct afs_addr_list *afs_vl_get_addrs_u(struct afs_net *net, | |||
286 | if (!call) | 283 | if (!call) |
287 | return ERR_PTR(-ENOMEM); | 284 | return ERR_PTR(-ENOMEM); |
288 | 285 | ||
289 | call->key = key; | 286 | call->key = vc->key; |
290 | call->reply[0] = NULL; | 287 | call->reply[0] = NULL; |
291 | call->ret_reply0 = true; | 288 | call->ret_reply0 = true; |
292 | 289 | ||
@@ -307,7 +304,7 @@ struct afs_addr_list *afs_vl_get_addrs_u(struct afs_net *net, | |||
307 | r->uuid.node[i] = htonl(u->node[i]); | 304 | r->uuid.node[i] = htonl(u->node[i]); |
308 | 305 | ||
309 | trace_afs_make_vl_call(call); | 306 | trace_afs_make_vl_call(call); |
310 | return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false); | 307 | return (struct afs_addr_list *)afs_make_call(&vc->ac, call, GFP_KERNEL, false); |
311 | } | 308 | } |
312 | 309 | ||
313 | /* | 310 | /* |
@@ -318,54 +315,51 @@ static int afs_deliver_vl_get_capabilities(struct afs_call *call) | |||
318 | u32 count; | 315 | u32 count; |
319 | int ret; | 316 | int ret; |
320 | 317 | ||
321 | _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); | 318 | _enter("{%u,%zu/%u}", |
319 | call->unmarshall, iov_iter_count(call->_iter), call->count); | ||
322 | 320 | ||
323 | again: | ||
324 | switch (call->unmarshall) { | 321 | switch (call->unmarshall) { |
325 | case 0: | 322 | case 0: |
326 | call->offset = 0; | 323 | afs_extract_to_tmp(call); |
327 | call->unmarshall++; | 324 | call->unmarshall++; |
328 | 325 | ||
329 | /* Extract the capabilities word count */ | 326 | /* Extract the capabilities word count */ |
330 | case 1: | 327 | case 1: |
331 | ret = afs_extract_data(call, &call->tmp, | 328 | ret = afs_extract_data(call, true); |
332 | 1 * sizeof(__be32), | ||
333 | true); | ||
334 | if (ret < 0) | 329 | if (ret < 0) |
335 | return ret; | 330 | return ret; |
336 | 331 | ||
337 | count = ntohl(call->tmp); | 332 | count = ntohl(call->tmp); |
338 | |||
339 | call->count = count; | 333 | call->count = count; |
340 | call->count2 = count; | 334 | call->count2 = count; |
341 | call->offset = 0; | 335 | |
342 | call->unmarshall++; | 336 | call->unmarshall++; |
337 | afs_extract_discard(call, count * sizeof(__be32)); | ||
343 | 338 | ||
344 | /* Extract capabilities words */ | 339 | /* Extract capabilities words */ |
345 | case 2: | 340 | case 2: |
346 | count = min(call->count, 16U); | 341 | ret = afs_extract_data(call, false); |
347 | ret = afs_extract_data(call, call->buffer, | ||
348 | count * sizeof(__be32), | ||
349 | call->count > 16); | ||
350 | if (ret < 0) | 342 | if (ret < 0) |
351 | return ret; | 343 | return ret; |
352 | 344 | ||
353 | /* TODO: Examine capabilities */ | 345 | /* TODO: Examine capabilities */ |
354 | 346 | ||
355 | call->count -= count; | ||
356 | if (call->count > 0) | ||
357 | goto again; | ||
358 | call->offset = 0; | ||
359 | call->unmarshall++; | 347 | call->unmarshall++; |
360 | break; | 348 | break; |
361 | } | 349 | } |
362 | 350 | ||
363 | call->reply[0] = (void *)(unsigned long)call->service_id; | ||
364 | |||
365 | _leave(" = 0 [done]"); | 351 | _leave(" = 0 [done]"); |
366 | return 0; | 352 | return 0; |
367 | } | 353 | } |
368 | 354 | ||
355 | static void afs_destroy_vl_get_capabilities(struct afs_call *call) | ||
356 | { | ||
357 | struct afs_vlserver *server = call->reply[0]; | ||
358 | |||
359 | afs_put_vlserver(call->net, server); | ||
360 | afs_flat_call_destructor(call); | ||
361 | } | ||
362 | |||
369 | /* | 363 | /* |
370 | * VL.GetCapabilities operation type | 364 | * VL.GetCapabilities operation type |
371 | */ | 365 | */ |
@@ -373,11 +367,12 @@ static const struct afs_call_type afs_RXVLGetCapabilities = { | |||
373 | .name = "VL.GetCapabilities", | 367 | .name = "VL.GetCapabilities", |
374 | .op = afs_VL_GetCapabilities, | 368 | .op = afs_VL_GetCapabilities, |
375 | .deliver = afs_deliver_vl_get_capabilities, | 369 | .deliver = afs_deliver_vl_get_capabilities, |
376 | .destructor = afs_flat_call_destructor, | 370 | .done = afs_vlserver_probe_result, |
371 | .destructor = afs_destroy_vl_get_capabilities, | ||
377 | }; | 372 | }; |
378 | 373 | ||
379 | /* | 374 | /* |
380 | * Probe a fileserver for the capabilities that it supports. This can | 375 | * Probe a volume server for the capabilities that it supports. This can |
381 | * return up to 196 words. | 376 | * return up to 196 words. |
382 | * | 377 | * |
383 | * We use this to probe for service upgrade to determine what the server at the | 378 | * We use this to probe for service upgrade to determine what the server at the |
@@ -385,7 +380,10 @@ static const struct afs_call_type afs_RXVLGetCapabilities = { | |||
385 | */ | 380 | */ |
386 | int afs_vl_get_capabilities(struct afs_net *net, | 381 | int afs_vl_get_capabilities(struct afs_net *net, |
387 | struct afs_addr_cursor *ac, | 382 | struct afs_addr_cursor *ac, |
388 | struct key *key) | 383 | struct key *key, |
384 | struct afs_vlserver *server, | ||
385 | unsigned int server_index, | ||
386 | bool async) | ||
389 | { | 387 | { |
390 | struct afs_call *call; | 388 | struct afs_call *call; |
391 | __be32 *bp; | 389 | __be32 *bp; |
@@ -397,9 +395,10 @@ int afs_vl_get_capabilities(struct afs_net *net, | |||
397 | return -ENOMEM; | 395 | return -ENOMEM; |
398 | 396 | ||
399 | call->key = key; | 397 | call->key = key; |
400 | call->upgrade = true; /* Let's see if this is a YFS server */ | 398 | call->reply[0] = afs_get_vlserver(server); |
401 | call->reply[0] = (void *)VLGETCAPABILITIES; | 399 | call->reply[1] = (void *)(long)server_index; |
402 | call->ret_reply0 = true; | 400 | call->upgrade = true; |
401 | call->want_reply_time = true; | ||
403 | 402 | ||
404 | /* marshall the parameters */ | 403 | /* marshall the parameters */ |
405 | bp = call->request; | 404 | bp = call->request; |
@@ -407,7 +406,7 @@ int afs_vl_get_capabilities(struct afs_net *net, | |||
407 | 406 | ||
408 | /* Can't take a ref on server */ | 407 | /* Can't take a ref on server */ |
409 | trace_afs_make_vl_call(call); | 408 | trace_afs_make_vl_call(call); |
410 | return afs_make_call(ac, call, GFP_KERNEL, false); | 409 | return afs_make_call(ac, call, GFP_KERNEL, async); |
411 | } | 410 | } |
412 | 411 | ||
413 | /* | 412 | /* |
@@ -426,22 +425,19 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) | |||
426 | u32 uniquifier, size; | 425 | u32 uniquifier, size; |
427 | int ret; | 426 | int ret; |
428 | 427 | ||
429 | _enter("{%u,%zu/%u,%u}", call->unmarshall, call->offset, call->count, call->count2); | 428 | _enter("{%u,%zu,%u}", |
429 | call->unmarshall, iov_iter_count(call->_iter), call->count2); | ||
430 | 430 | ||
431 | again: | ||
432 | switch (call->unmarshall) { | 431 | switch (call->unmarshall) { |
433 | case 0: | 432 | case 0: |
434 | call->offset = 0; | 433 | afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32)); |
435 | call->unmarshall = 1; | 434 | call->unmarshall = 1; |
436 | 435 | ||
437 | /* Extract the returned uuid, uniquifier, fsEndpoints count and | 436 | /* Extract the returned uuid, uniquifier, fsEndpoints count and |
438 | * either the first fsEndpoint type or the volEndpoints | 437 | * either the first fsEndpoint type or the volEndpoints |
439 | * count if there are no fsEndpoints. */ | 438 | * count if there are no fsEndpoints. */ |
440 | case 1: | 439 | case 1: |
441 | ret = afs_extract_data(call, call->buffer, | 440 | ret = afs_extract_data(call, true); |
442 | sizeof(uuid_t) + | ||
443 | 3 * sizeof(__be32), | ||
444 | true); | ||
445 | if (ret < 0) | 441 | if (ret < 0) |
446 | return ret; | 442 | return ret; |
447 | 443 | ||
@@ -451,22 +447,19 @@ again: | |||
451 | call->count2 = ntohl(*bp); /* Type or next count */ | 447 | call->count2 = ntohl(*bp); /* Type or next count */ |
452 | 448 | ||
453 | if (call->count > YFS_MAXENDPOINTS) | 449 | if (call->count > YFS_MAXENDPOINTS) |
454 | return afs_protocol_error(call, -EBADMSG); | 450 | return afs_protocol_error(call, -EBADMSG, |
451 | afs_eproto_yvl_fsendpt_num); | ||
455 | 452 | ||
456 | alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); | 453 | alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); |
457 | if (!alist) | 454 | if (!alist) |
458 | return -ENOMEM; | 455 | return -ENOMEM; |
459 | alist->version = uniquifier; | 456 | alist->version = uniquifier; |
460 | call->reply[0] = alist; | 457 | call->reply[0] = alist; |
461 | call->offset = 0; | ||
462 | 458 | ||
463 | if (call->count == 0) | 459 | if (call->count == 0) |
464 | goto extract_volendpoints; | 460 | goto extract_volendpoints; |
465 | 461 | ||
466 | call->unmarshall = 2; | 462 | next_fsendpoint: |
467 | |||
468 | /* Extract fsEndpoints[] entries */ | ||
469 | case 2: | ||
470 | switch (call->count2) { | 463 | switch (call->count2) { |
471 | case YFS_ENDPOINT_IPV4: | 464 | case YFS_ENDPOINT_IPV4: |
472 | size = sizeof(__be32) * (1 + 1 + 1); | 465 | size = sizeof(__be32) * (1 + 1 + 1); |
@@ -475,11 +468,17 @@ again: | |||
475 | size = sizeof(__be32) * (1 + 4 + 1); | 468 | size = sizeof(__be32) * (1 + 4 + 1); |
476 | break; | 469 | break; |
477 | default: | 470 | default: |
478 | return afs_protocol_error(call, -EBADMSG); | 471 | return afs_protocol_error(call, -EBADMSG, |
472 | afs_eproto_yvl_fsendpt_type); | ||
479 | } | 473 | } |
480 | 474 | ||
481 | size += sizeof(__be32); | 475 | size += sizeof(__be32); |
482 | ret = afs_extract_data(call, call->buffer, size, true); | 476 | afs_extract_to_buf(call, size); |
477 | call->unmarshall = 2; | ||
478 | |||
479 | /* Extract fsEndpoints[] entries */ | ||
480 | case 2: | ||
481 | ret = afs_extract_data(call, true); | ||
483 | if (ret < 0) | 482 | if (ret < 0) |
484 | return ret; | 483 | return ret; |
485 | 484 | ||
@@ -488,18 +487,21 @@ again: | |||
488 | switch (call->count2) { | 487 | switch (call->count2) { |
489 | case YFS_ENDPOINT_IPV4: | 488 | case YFS_ENDPOINT_IPV4: |
490 | if (ntohl(bp[0]) != sizeof(__be32) * 2) | 489 | if (ntohl(bp[0]) != sizeof(__be32) * 2) |
491 | return afs_protocol_error(call, -EBADMSG); | 490 | return afs_protocol_error(call, -EBADMSG, |
491 | afs_eproto_yvl_fsendpt4_len); | ||
492 | afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); | 492 | afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); |
493 | bp += 3; | 493 | bp += 3; |
494 | break; | 494 | break; |
495 | case YFS_ENDPOINT_IPV6: | 495 | case YFS_ENDPOINT_IPV6: |
496 | if (ntohl(bp[0]) != sizeof(__be32) * 5) | 496 | if (ntohl(bp[0]) != sizeof(__be32) * 5) |
497 | return afs_protocol_error(call, -EBADMSG); | 497 | return afs_protocol_error(call, -EBADMSG, |
498 | afs_eproto_yvl_fsendpt6_len); | ||
498 | afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); | 499 | afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); |
499 | bp += 6; | 500 | bp += 6; |
500 | break; | 501 | break; |
501 | default: | 502 | default: |
502 | return afs_protocol_error(call, -EBADMSG); | 503 | return afs_protocol_error(call, -EBADMSG, |
504 | afs_eproto_yvl_fsendpt_type); | ||
503 | } | 505 | } |
504 | 506 | ||
505 | /* Got either the type of the next entry or the count of | 507 | /* Got either the type of the next entry or the count of |
@@ -507,10 +509,9 @@ again: | |||
507 | */ | 509 | */ |
508 | call->count2 = ntohl(*bp++); | 510 | call->count2 = ntohl(*bp++); |
509 | 511 | ||
510 | call->offset = 0; | ||
511 | call->count--; | 512 | call->count--; |
512 | if (call->count > 0) | 513 | if (call->count > 0) |
513 | goto again; | 514 | goto next_fsendpoint; |
514 | 515 | ||
515 | extract_volendpoints: | 516 | extract_volendpoints: |
516 | /* Extract the list of volEndpoints. */ | 517 | /* Extract the list of volEndpoints. */ |
@@ -518,8 +519,10 @@ again: | |||
518 | if (!call->count) | 519 | if (!call->count) |
519 | goto end; | 520 | goto end; |
520 | if (call->count > YFS_MAXENDPOINTS) | 521 | if (call->count > YFS_MAXENDPOINTS) |
521 | return afs_protocol_error(call, -EBADMSG); | 522 | return afs_protocol_error(call, -EBADMSG, |
523 | afs_eproto_yvl_vlendpt_type); | ||
522 | 524 | ||
525 | afs_extract_to_buf(call, 1 * sizeof(__be32)); | ||
523 | call->unmarshall = 3; | 526 | call->unmarshall = 3; |
524 | 527 | ||
525 | /* Extract the type of volEndpoints[0]. Normally we would | 528 | /* Extract the type of volEndpoints[0]. Normally we would |
@@ -527,17 +530,14 @@ again: | |||
527 | * data of the current one, but this is the first... | 530 | * data of the current one, but this is the first... |
528 | */ | 531 | */ |
529 | case 3: | 532 | case 3: |
530 | ret = afs_extract_data(call, call->buffer, sizeof(__be32), true); | 533 | ret = afs_extract_data(call, true); |
531 | if (ret < 0) | 534 | if (ret < 0) |
532 | return ret; | 535 | return ret; |
533 | 536 | ||
534 | bp = call->buffer; | 537 | bp = call->buffer; |
535 | call->count2 = ntohl(*bp++); | ||
536 | call->offset = 0; | ||
537 | call->unmarshall = 4; | ||
538 | 538 | ||
539 | /* Extract volEndpoints[] entries */ | 539 | next_volendpoint: |
540 | case 4: | 540 | call->count2 = ntohl(*bp++); |
541 | switch (call->count2) { | 541 | switch (call->count2) { |
542 | case YFS_ENDPOINT_IPV4: | 542 | case YFS_ENDPOINT_IPV4: |
543 | size = sizeof(__be32) * (1 + 1 + 1); | 543 | size = sizeof(__be32) * (1 + 1 + 1); |
@@ -546,12 +546,18 @@ again: | |||
546 | size = sizeof(__be32) * (1 + 4 + 1); | 546 | size = sizeof(__be32) * (1 + 4 + 1); |
547 | break; | 547 | break; |
548 | default: | 548 | default: |
549 | return afs_protocol_error(call, -EBADMSG); | 549 | return afs_protocol_error(call, -EBADMSG, |
550 | afs_eproto_yvl_vlendpt_type); | ||
550 | } | 551 | } |
551 | 552 | ||
552 | if (call->count > 1) | 553 | if (call->count > 1) |
553 | size += sizeof(__be32); | 554 | size += sizeof(__be32); /* Get next type too */ |
554 | ret = afs_extract_data(call, call->buffer, size, true); | 555 | afs_extract_to_buf(call, size); |
556 | call->unmarshall = 4; | ||
557 | |||
558 | /* Extract volEndpoints[] entries */ | ||
559 | case 4: | ||
560 | ret = afs_extract_data(call, true); | ||
555 | if (ret < 0) | 561 | if (ret < 0) |
556 | return ret; | 562 | return ret; |
557 | 563 | ||
@@ -559,34 +565,35 @@ again: | |||
559 | switch (call->count2) { | 565 | switch (call->count2) { |
560 | case YFS_ENDPOINT_IPV4: | 566 | case YFS_ENDPOINT_IPV4: |
561 | if (ntohl(bp[0]) != sizeof(__be32) * 2) | 567 | if (ntohl(bp[0]) != sizeof(__be32) * 2) |
562 | return afs_protocol_error(call, -EBADMSG); | 568 | return afs_protocol_error(call, -EBADMSG, |
569 | afs_eproto_yvl_vlendpt4_len); | ||
563 | bp += 3; | 570 | bp += 3; |
564 | break; | 571 | break; |
565 | case YFS_ENDPOINT_IPV6: | 572 | case YFS_ENDPOINT_IPV6: |
566 | if (ntohl(bp[0]) != sizeof(__be32) * 5) | 573 | if (ntohl(bp[0]) != sizeof(__be32) * 5) |
567 | return afs_protocol_error(call, -EBADMSG); | 574 | return afs_protocol_error(call, -EBADMSG, |
575 | afs_eproto_yvl_vlendpt6_len); | ||
568 | bp += 6; | 576 | bp += 6; |
569 | break; | 577 | break; |
570 | default: | 578 | default: |
571 | return afs_protocol_error(call, -EBADMSG); | 579 | return afs_protocol_error(call, -EBADMSG, |
580 | afs_eproto_yvl_vlendpt_type); | ||
572 | } | 581 | } |
573 | 582 | ||
574 | /* Got either the type of the next entry or the count of | 583 | /* Got either the type of the next entry or the count of |
575 | * volEndpoints if no more fsEndpoints. | 584 | * volEndpoints if no more fsEndpoints. |
576 | */ | 585 | */ |
577 | call->offset = 0; | ||
578 | call->count--; | 586 | call->count--; |
579 | if (call->count > 0) { | 587 | if (call->count > 0) |
580 | call->count2 = ntohl(*bp++); | 588 | goto next_volendpoint; |
581 | goto again; | ||
582 | } | ||
583 | 589 | ||
584 | end: | 590 | end: |
591 | afs_extract_discard(call, 0); | ||
585 | call->unmarshall = 5; | 592 | call->unmarshall = 5; |
586 | 593 | ||
587 | /* Done */ | 594 | /* Done */ |
588 | case 5: | 595 | case 5: |
589 | ret = afs_extract_data(call, call->buffer, 0, false); | 596 | ret = afs_extract_data(call, false); |
590 | if (ret < 0) | 597 | if (ret < 0) |
591 | return ret; | 598 | return ret; |
592 | call->unmarshall = 6; | 599 | call->unmarshall = 6; |
@@ -596,11 +603,6 @@ again: | |||
596 | } | 603 | } |
597 | 604 | ||
598 | alist = call->reply[0]; | 605 | alist = call->reply[0]; |
599 | |||
600 | /* Start with IPv6 if available. */ | ||
601 | if (alist->nr_ipv4 < alist->nr_addrs) | ||
602 | alist->index = alist->nr_ipv4; | ||
603 | |||
604 | _leave(" = 0 [done]"); | 606 | _leave(" = 0 [done]"); |
605 | return 0; | 607 | return 0; |
606 | } | 608 | } |
@@ -619,12 +621,11 @@ static const struct afs_call_type afs_YFSVLGetEndpoints = { | |||
619 | * Dispatch an operation to get the addresses for a server, where the server is | 621 | * Dispatch an operation to get the addresses for a server, where the server is |
620 | * nominated by UUID. | 622 | * nominated by UUID. |
621 | */ | 623 | */ |
622 | struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_net *net, | 624 | struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc, |
623 | struct afs_addr_cursor *ac, | ||
624 | struct key *key, | ||
625 | const uuid_t *uuid) | 625 | const uuid_t *uuid) |
626 | { | 626 | { |
627 | struct afs_call *call; | 627 | struct afs_call *call; |
628 | struct afs_net *net = vc->cell->net; | ||
628 | __be32 *bp; | 629 | __be32 *bp; |
629 | 630 | ||
630 | _enter(""); | 631 | _enter(""); |
@@ -635,7 +636,7 @@ struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_net *net, | |||
635 | if (!call) | 636 | if (!call) |
636 | return ERR_PTR(-ENOMEM); | 637 | return ERR_PTR(-ENOMEM); |
637 | 638 | ||
638 | call->key = key; | 639 | call->key = vc->key; |
639 | call->reply[0] = NULL; | 640 | call->reply[0] = NULL; |
640 | call->ret_reply0 = true; | 641 | call->ret_reply0 = true; |
641 | 642 | ||
@@ -646,5 +647,5 @@ struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_net *net, | |||
646 | memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */ | 647 | memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */ |
647 | 648 | ||
648 | trace_afs_make_vl_call(call); | 649 | trace_afs_make_vl_call(call); |
649 | return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false); | 650 | return (struct afs_addr_list *)afs_make_call(&vc->ac, call, GFP_KERNEL, false); |
650 | } | 651 | } |
diff --git a/fs/afs/volume.c b/fs/afs/volume.c index 3037bd01f617..00975ed3640f 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c | |||
@@ -74,55 +74,19 @@ static struct afs_vldb_entry *afs_vl_lookup_vldb(struct afs_cell *cell, | |||
74 | const char *volname, | 74 | const char *volname, |
75 | size_t volnamesz) | 75 | size_t volnamesz) |
76 | { | 76 | { |
77 | struct afs_addr_cursor ac; | 77 | struct afs_vldb_entry *vldb = ERR_PTR(-EDESTADDRREQ); |
78 | struct afs_vldb_entry *vldb; | 78 | struct afs_vl_cursor vc; |
79 | int ret; | 79 | int ret; |
80 | 80 | ||
81 | ret = afs_set_vl_cursor(&ac, cell); | 81 | if (!afs_begin_vlserver_operation(&vc, cell, key)) |
82 | if (ret < 0) | 82 | return ERR_PTR(-ERESTARTSYS); |
83 | return ERR_PTR(ret); | 83 | |
84 | 84 | while (afs_select_vlserver(&vc)) { | |
85 | while (afs_iterate_addresses(&ac)) { | 85 | vldb = afs_vl_get_entry_by_name_u(&vc, volname, volnamesz); |
86 | if (!test_bit(ac.index, &ac.alist->probed)) { | ||
87 | ret = afs_vl_get_capabilities(cell->net, &ac, key); | ||
88 | switch (ret) { | ||
89 | case VL_SERVICE: | ||
90 | clear_bit(ac.index, &ac.alist->yfs); | ||
91 | set_bit(ac.index, &ac.alist->probed); | ||
92 | ac.addr->srx_service = ret; | ||
93 | break; | ||
94 | case YFS_VL_SERVICE: | ||
95 | set_bit(ac.index, &ac.alist->yfs); | ||
96 | set_bit(ac.index, &ac.alist->probed); | ||
97 | ac.addr->srx_service = ret; | ||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | vldb = afs_vl_get_entry_by_name_u(cell->net, &ac, key, | ||
103 | volname, volnamesz); | ||
104 | switch (ac.error) { | ||
105 | case 0: | ||
106 | afs_end_cursor(&ac); | ||
107 | return vldb; | ||
108 | case -ECONNABORTED: | ||
109 | ac.error = afs_abort_to_error(ac.abort_code); | ||
110 | goto error; | ||
111 | case -ENOMEM: | ||
112 | case -ENONET: | ||
113 | goto error; | ||
114 | case -ENETUNREACH: | ||
115 | case -EHOSTUNREACH: | ||
116 | case -ECONNREFUSED: | ||
117 | break; | ||
118 | default: | ||
119 | ac.error = -EIO; | ||
120 | goto error; | ||
121 | } | ||
122 | } | 86 | } |
123 | 87 | ||
124 | error: | 88 | ret = afs_end_vlserver_operation(&vc); |
125 | return ERR_PTR(afs_end_cursor(&ac)); | 89 | return ret < 0 ? ERR_PTR(ret) : vldb; |
126 | } | 90 | } |
127 | 91 | ||
128 | /* | 92 | /* |
@@ -270,7 +234,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key) | |||
270 | /* We look up an ID by passing it as a decimal string in the | 234 | /* We look up an ID by passing it as a decimal string in the |
271 | * operation's name parameter. | 235 | * operation's name parameter. |
272 | */ | 236 | */ |
273 | idsz = sprintf(idbuf, "%u", volume->vid); | 237 | idsz = sprintf(idbuf, "%llu", volume->vid); |
274 | 238 | ||
275 | vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz); | 239 | vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz); |
276 | if (IS_ERR(vldb)) { | 240 | if (IS_ERR(vldb)) { |
diff --git a/fs/afs/write.c b/fs/afs/write.c index 19c04caf3c01..72efcfcf9f95 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
@@ -33,10 +33,21 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key, | |||
33 | loff_t pos, unsigned int len, struct page *page) | 33 | loff_t pos, unsigned int len, struct page *page) |
34 | { | 34 | { |
35 | struct afs_read *req; | 35 | struct afs_read *req; |
36 | size_t p; | ||
37 | void *data; | ||
36 | int ret; | 38 | int ret; |
37 | 39 | ||
38 | _enter(",,%llu", (unsigned long long)pos); | 40 | _enter(",,%llu", (unsigned long long)pos); |
39 | 41 | ||
42 | if (pos >= vnode->vfs_inode.i_size) { | ||
43 | p = pos & ~PAGE_MASK; | ||
44 | ASSERTCMP(p + len, <=, PAGE_SIZE); | ||
45 | data = kmap(page); | ||
46 | memset(data + p, 0, len); | ||
47 | kunmap(page); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
40 | req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), | 51 | req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), |
41 | GFP_KERNEL); | 52 | GFP_KERNEL); |
42 | if (!req) | 53 | if (!req) |
@@ -81,7 +92,7 @@ int afs_write_begin(struct file *file, struct address_space *mapping, | |||
81 | pgoff_t index = pos >> PAGE_SHIFT; | 92 | pgoff_t index = pos >> PAGE_SHIFT; |
82 | int ret; | 93 | int ret; |
83 | 94 | ||
84 | _enter("{%x:%u},{%lx},%u,%u", | 95 | _enter("{%llx:%llu},{%lx},%u,%u", |
85 | vnode->fid.vid, vnode->fid.vnode, index, from, to); | 96 | vnode->fid.vid, vnode->fid.vnode, index, from, to); |
86 | 97 | ||
87 | /* We want to store information about how much of a page is altered in | 98 | /* We want to store information about how much of a page is altered in |
@@ -181,7 +192,7 @@ int afs_write_end(struct file *file, struct address_space *mapping, | |||
181 | loff_t i_size, maybe_i_size; | 192 | loff_t i_size, maybe_i_size; |
182 | int ret; | 193 | int ret; |
183 | 194 | ||
184 | _enter("{%x:%u},{%lx}", | 195 | _enter("{%llx:%llu},{%lx}", |
185 | vnode->fid.vid, vnode->fid.vnode, page->index); | 196 | vnode->fid.vid, vnode->fid.vnode, page->index); |
186 | 197 | ||
187 | maybe_i_size = pos + copied; | 198 | maybe_i_size = pos + copied; |
@@ -230,7 +241,7 @@ static void afs_kill_pages(struct address_space *mapping, | |||
230 | struct pagevec pv; | 241 | struct pagevec pv; |
231 | unsigned count, loop; | 242 | unsigned count, loop; |
232 | 243 | ||
233 | _enter("{%x:%u},%lx-%lx", | 244 | _enter("{%llx:%llu},%lx-%lx", |
234 | vnode->fid.vid, vnode->fid.vnode, first, last); | 245 | vnode->fid.vid, vnode->fid.vnode, first, last); |
235 | 246 | ||
236 | pagevec_init(&pv); | 247 | pagevec_init(&pv); |
@@ -272,7 +283,7 @@ static void afs_redirty_pages(struct writeback_control *wbc, | |||
272 | struct pagevec pv; | 283 | struct pagevec pv; |
273 | unsigned count, loop; | 284 | unsigned count, loop; |
274 | 285 | ||
275 | _enter("{%x:%u},%lx-%lx", | 286 | _enter("{%llx:%llu},%lx-%lx", |
276 | vnode->fid.vid, vnode->fid.vnode, first, last); | 287 | vnode->fid.vid, vnode->fid.vnode, first, last); |
277 | 288 | ||
278 | pagevec_init(&pv); | 289 | pagevec_init(&pv); |
@@ -314,7 +325,7 @@ static int afs_store_data(struct address_space *mapping, | |||
314 | struct list_head *p; | 325 | struct list_head *p; |
315 | int ret = -ENOKEY, ret2; | 326 | int ret = -ENOKEY, ret2; |
316 | 327 | ||
317 | _enter("%s{%x:%u.%u},%lx,%lx,%x,%x", | 328 | _enter("%s{%llx:%llu.%u},%lx,%lx,%x,%x", |
318 | vnode->volume->name, | 329 | vnode->volume->name, |
319 | vnode->fid.vid, | 330 | vnode->fid.vid, |
320 | vnode->fid.vnode, | 331 | vnode->fid.vnode, |
@@ -533,6 +544,7 @@ no_more: | |||
533 | case -ENOENT: | 544 | case -ENOENT: |
534 | case -ENOMEDIUM: | 545 | case -ENOMEDIUM: |
535 | case -ENXIO: | 546 | case -ENXIO: |
547 | trace_afs_file_error(vnode, ret, afs_file_error_writeback_fail); | ||
536 | afs_kill_pages(mapping, first, last); | 548 | afs_kill_pages(mapping, first, last); |
537 | mapping_set_error(mapping, ret); | 549 | mapping_set_error(mapping, ret); |
538 | break; | 550 | break; |
@@ -675,7 +687,7 @@ void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call) | |||
675 | unsigned count, loop; | 687 | unsigned count, loop; |
676 | pgoff_t first = call->first, last = call->last; | 688 | pgoff_t first = call->first, last = call->last; |
677 | 689 | ||
678 | _enter("{%x:%u},{%lx-%lx}", | 690 | _enter("{%llx:%llu},{%lx-%lx}", |
679 | vnode->fid.vid, vnode->fid.vnode, first, last); | 691 | vnode->fid.vid, vnode->fid.vnode, first, last); |
680 | 692 | ||
681 | pagevec_init(&pv); | 693 | pagevec_init(&pv); |
@@ -714,7 +726,7 @@ ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) | |||
714 | ssize_t result; | 726 | ssize_t result; |
715 | size_t count = iov_iter_count(from); | 727 | size_t count = iov_iter_count(from); |
716 | 728 | ||
717 | _enter("{%x.%u},{%zu},", | 729 | _enter("{%llx:%llu},{%zu},", |
718 | vnode->fid.vid, vnode->fid.vnode, count); | 730 | vnode->fid.vid, vnode->fid.vnode, count); |
719 | 731 | ||
720 | if (IS_SWAPFILE(&vnode->vfs_inode)) { | 732 | if (IS_SWAPFILE(&vnode->vfs_inode)) { |
@@ -742,7 +754,7 @@ int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
742 | struct inode *inode = file_inode(file); | 754 | struct inode *inode = file_inode(file); |
743 | struct afs_vnode *vnode = AFS_FS_I(inode); | 755 | struct afs_vnode *vnode = AFS_FS_I(inode); |
744 | 756 | ||
745 | _enter("{%x:%u},{n=%pD},%d", | 757 | _enter("{%llx:%llu},{n=%pD},%d", |
746 | vnode->fid.vid, vnode->fid.vnode, file, | 758 | vnode->fid.vid, vnode->fid.vnode, file, |
747 | datasync); | 759 | datasync); |
748 | 760 | ||
@@ -760,7 +772,7 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) | |||
760 | struct afs_vnode *vnode = AFS_FS_I(inode); | 772 | struct afs_vnode *vnode = AFS_FS_I(inode); |
761 | unsigned long priv; | 773 | unsigned long priv; |
762 | 774 | ||
763 | _enter("{{%x:%u}},{%lx}", | 775 | _enter("{{%llx:%llu}},{%lx}", |
764 | vnode->fid.vid, vnode->fid.vnode, vmf->page->index); | 776 | vnode->fid.vid, vnode->fid.vnode, vmf->page->index); |
765 | 777 | ||
766 | sb_start_pagefault(inode->i_sb); | 778 | sb_start_pagefault(inode->i_sb); |
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c index cfcc674e64a5..a2cdf25573e2 100644 --- a/fs/afs/xattr.c +++ b/fs/afs/xattr.c | |||
@@ -72,7 +72,7 @@ static int afs_xattr_get_fid(const struct xattr_handler *handler, | |||
72 | char text[8 + 1 + 8 + 1 + 8 + 1]; | 72 | char text[8 + 1 + 8 + 1 + 8 + 1]; |
73 | size_t len; | 73 | size_t len; |
74 | 74 | ||
75 | len = sprintf(text, "%x:%x:%x", | 75 | len = sprintf(text, "%llx:%llx:%x", |
76 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); | 76 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); |
77 | if (size == 0) | 77 | if (size == 0) |
78 | return len; | 78 | return len; |
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c new file mode 100644 index 000000000000..12658c1363ae --- /dev/null +++ b/fs/afs/yfsclient.c | |||
@@ -0,0 +1,2184 @@ | |||
1 | /* YFS File Server client stubs | ||
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 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/circ_buf.h> | ||
16 | #include <linux/iversion.h> | ||
17 | #include "internal.h" | ||
18 | #include "afs_fs.h" | ||
19 | #include "xdr_fs.h" | ||
20 | #include "protocol_yfs.h" | ||
21 | |||
22 | static const struct afs_fid afs_zero_fid; | ||
23 | |||
24 | static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi) | ||
25 | { | ||
26 | call->cbi = afs_get_cb_interest(cbi); | ||
27 | } | ||
28 | |||
29 | #define xdr_size(x) (sizeof(*x) / sizeof(__be32)) | ||
30 | |||
31 | static void xdr_decode_YFSFid(const __be32 **_bp, struct afs_fid *fid) | ||
32 | { | ||
33 | const struct yfs_xdr_YFSFid *x = (const void *)*_bp; | ||
34 | |||
35 | fid->vid = xdr_to_u64(x->volume); | ||
36 | fid->vnode = xdr_to_u64(x->vnode.lo); | ||
37 | fid->vnode_hi = ntohl(x->vnode.hi); | ||
38 | fid->unique = ntohl(x->vnode.unique); | ||
39 | *_bp += xdr_size(x); | ||
40 | } | ||
41 | |||
42 | static __be32 *xdr_encode_u32(__be32 *bp, u32 n) | ||
43 | { | ||
44 | *bp++ = htonl(n); | ||
45 | return bp; | ||
46 | } | ||
47 | |||
48 | static __be32 *xdr_encode_u64(__be32 *bp, u64 n) | ||
49 | { | ||
50 | struct yfs_xdr_u64 *x = (void *)bp; | ||
51 | |||
52 | *x = u64_to_xdr(n); | ||
53 | return bp + xdr_size(x); | ||
54 | } | ||
55 | |||
56 | static __be32 *xdr_encode_YFSFid(__be32 *bp, struct afs_fid *fid) | ||
57 | { | ||
58 | struct yfs_xdr_YFSFid *x = (void *)bp; | ||
59 | |||
60 | x->volume = u64_to_xdr(fid->vid); | ||
61 | x->vnode.lo = u64_to_xdr(fid->vnode); | ||
62 | x->vnode.hi = htonl(fid->vnode_hi); | ||
63 | x->vnode.unique = htonl(fid->unique); | ||
64 | return bp + xdr_size(x); | ||
65 | } | ||
66 | |||
67 | static size_t xdr_strlen(unsigned int len) | ||
68 | { | ||
69 | return sizeof(__be32) + round_up(len, sizeof(__be32)); | ||
70 | } | ||
71 | |||
72 | static __be32 *xdr_encode_string(__be32 *bp, const char *p, unsigned int len) | ||
73 | { | ||
74 | bp = xdr_encode_u32(bp, len); | ||
75 | bp = memcpy(bp, p, len); | ||
76 | if (len & 3) { | ||
77 | unsigned int pad = 4 - (len & 3); | ||
78 | |||
79 | memset((u8 *)bp + len, 0, pad); | ||
80 | len += pad; | ||
81 | } | ||
82 | |||
83 | return bp + len / sizeof(__be32); | ||
84 | } | ||
85 | |||
86 | static s64 linux_to_yfs_time(const struct timespec64 *t) | ||
87 | { | ||
88 | /* Convert to 100ns intervals. */ | ||
89 | return (u64)t->tv_sec * 10000000 + t->tv_nsec/100; | ||
90 | } | ||
91 | |||
92 | static __be32 *xdr_encode_YFSStoreStatus_mode(__be32 *bp, mode_t mode) | ||
93 | { | ||
94 | struct yfs_xdr_YFSStoreStatus *x = (void *)bp; | ||
95 | |||
96 | x->mask = htonl(AFS_SET_MODE); | ||
97 | x->mode = htonl(mode & S_IALLUGO); | ||
98 | x->mtime_client = u64_to_xdr(0); | ||
99 | x->owner = u64_to_xdr(0); | ||
100 | x->group = u64_to_xdr(0); | ||
101 | return bp + xdr_size(x); | ||
102 | } | ||
103 | |||
104 | static __be32 *xdr_encode_YFSStoreStatus_mtime(__be32 *bp, const struct timespec64 *t) | ||
105 | { | ||
106 | struct yfs_xdr_YFSStoreStatus *x = (void *)bp; | ||
107 | s64 mtime = linux_to_yfs_time(t); | ||
108 | |||
109 | x->mask = htonl(AFS_SET_MTIME); | ||
110 | x->mode = htonl(0); | ||
111 | x->mtime_client = u64_to_xdr(mtime); | ||
112 | x->owner = u64_to_xdr(0); | ||
113 | x->group = u64_to_xdr(0); | ||
114 | return bp + xdr_size(x); | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * Convert a signed 100ns-resolution 64-bit time into a timespec. | ||
119 | */ | ||
120 | static struct timespec64 yfs_time_to_linux(s64 t) | ||
121 | { | ||
122 | struct timespec64 ts; | ||
123 | u64 abs_t; | ||
124 | |||
125 | /* | ||
126 | * Unfortunately can not use normal 64 bit division on 32 bit arch, but | ||
127 | * the alternative, do_div, does not work with negative numbers so have | ||
128 | * to special case them | ||
129 | */ | ||
130 | if (t < 0) { | ||
131 | abs_t = -t; | ||
132 | ts.tv_nsec = (time64_t)(do_div(abs_t, 10000000) * 100); | ||
133 | ts.tv_nsec = -ts.tv_nsec; | ||
134 | ts.tv_sec = -abs_t; | ||
135 | } else { | ||
136 | abs_t = t; | ||
137 | ts.tv_nsec = (time64_t)do_div(abs_t, 10000000) * 100; | ||
138 | ts.tv_sec = abs_t; | ||
139 | } | ||
140 | |||
141 | return ts; | ||
142 | } | ||
143 | |||
144 | static struct timespec64 xdr_to_time(const struct yfs_xdr_u64 xdr) | ||
145 | { | ||
146 | s64 t = xdr_to_u64(xdr); | ||
147 | |||
148 | return yfs_time_to_linux(t); | ||
149 | } | ||
150 | |||
151 | static void yfs_check_req(struct afs_call *call, __be32 *bp) | ||
152 | { | ||
153 | size_t len = (void *)bp - call->request; | ||
154 | |||
155 | if (len > call->request_size) | ||
156 | pr_err("kAFS: %s: Request buffer overflow (%zu>%u)\n", | ||
157 | call->type->name, len, call->request_size); | ||
158 | else if (len < call->request_size) | ||
159 | pr_warning("kAFS: %s: Request buffer underflow (%zu<%u)\n", | ||
160 | call->type->name, len, call->request_size); | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Dump a bad file status record. | ||
165 | */ | ||
166 | static void xdr_dump_bad(const __be32 *bp) | ||
167 | { | ||
168 | __be32 x[4]; | ||
169 | int i; | ||
170 | |||
171 | pr_notice("YFS XDR: Bad status record\n"); | ||
172 | for (i = 0; i < 5 * 4 * 4; i += 16) { | ||
173 | memcpy(x, bp, 16); | ||
174 | bp += 4; | ||
175 | pr_notice("%03x: %08x %08x %08x %08x\n", | ||
176 | i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3])); | ||
177 | } | ||
178 | |||
179 | memcpy(x, bp, 4); | ||
180 | pr_notice("0x50: %08x\n", ntohl(x[0])); | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Decode a YFSFetchStatus block | ||
185 | */ | ||
186 | static int xdr_decode_YFSFetchStatus(struct afs_call *call, | ||
187 | const __be32 **_bp, | ||
188 | struct afs_file_status *status, | ||
189 | struct afs_vnode *vnode, | ||
190 | const afs_dataversion_t *expected_version, | ||
191 | struct afs_read *read_req) | ||
192 | { | ||
193 | const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp; | ||
194 | u32 type; | ||
195 | u8 flags = 0; | ||
196 | |||
197 | status->abort_code = ntohl(xdr->abort_code); | ||
198 | if (status->abort_code != 0) { | ||
199 | if (vnode && status->abort_code == VNOVNODE) { | ||
200 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | ||
201 | status->nlink = 0; | ||
202 | __afs_break_callback(vnode); | ||
203 | } | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | type = ntohl(xdr->type); | ||
208 | switch (type) { | ||
209 | case AFS_FTYPE_FILE: | ||
210 | case AFS_FTYPE_DIR: | ||
211 | case AFS_FTYPE_SYMLINK: | ||
212 | if (type != status->type && | ||
213 | vnode && | ||
214 | !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { | ||
215 | pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n", | ||
216 | vnode->fid.vid, | ||
217 | vnode->fid.vnode, | ||
218 | vnode->fid.unique, | ||
219 | status->type, type); | ||
220 | goto bad; | ||
221 | } | ||
222 | status->type = type; | ||
223 | break; | ||
224 | default: | ||
225 | goto bad; | ||
226 | } | ||
227 | |||
228 | #define EXTRACT_M4(FIELD) \ | ||
229 | do { \ | ||
230 | u32 x = ntohl(xdr->FIELD); \ | ||
231 | if (status->FIELD != x) { \ | ||
232 | flags |= AFS_VNODE_META_CHANGED; \ | ||
233 | status->FIELD = x; \ | ||
234 | } \ | ||
235 | } while (0) | ||
236 | |||
237 | #define EXTRACT_M8(FIELD) \ | ||
238 | do { \ | ||
239 | u64 x = xdr_to_u64(xdr->FIELD); \ | ||
240 | if (status->FIELD != x) { \ | ||
241 | flags |= AFS_VNODE_META_CHANGED; \ | ||
242 | status->FIELD = x; \ | ||
243 | } \ | ||
244 | } while (0) | ||
245 | |||
246 | #define EXTRACT_D8(FIELD) \ | ||
247 | do { \ | ||
248 | u64 x = xdr_to_u64(xdr->FIELD); \ | ||
249 | if (status->FIELD != x) { \ | ||
250 | flags |= AFS_VNODE_DATA_CHANGED; \ | ||
251 | status->FIELD = x; \ | ||
252 | } \ | ||
253 | } while (0) | ||
254 | |||
255 | EXTRACT_M4(nlink); | ||
256 | EXTRACT_D8(size); | ||
257 | EXTRACT_D8(data_version); | ||
258 | EXTRACT_M8(author); | ||
259 | EXTRACT_M8(owner); | ||
260 | EXTRACT_M8(group); | ||
261 | EXTRACT_M4(mode); | ||
262 | EXTRACT_M4(caller_access); /* call ticket dependent */ | ||
263 | EXTRACT_M4(anon_access); | ||
264 | |||
265 | status->mtime_client = xdr_to_time(xdr->mtime_client); | ||
266 | status->mtime_server = xdr_to_time(xdr->mtime_server); | ||
267 | status->lock_count = ntohl(xdr->lock_count); | ||
268 | |||
269 | if (read_req) { | ||
270 | read_req->data_version = status->data_version; | ||
271 | read_req->file_size = status->size; | ||
272 | } | ||
273 | |||
274 | *_bp += xdr_size(xdr); | ||
275 | |||
276 | if (vnode) { | ||
277 | if (test_bit(AFS_VNODE_UNSET, &vnode->flags)) | ||
278 | flags |= AFS_VNODE_NOT_YET_SET; | ||
279 | afs_update_inode_from_status(vnode, status, expected_version, | ||
280 | flags); | ||
281 | } | ||
282 | |||
283 | return 0; | ||
284 | |||
285 | bad: | ||
286 | xdr_dump_bad(*_bp); | ||
287 | return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | * Decode the file status. We need to lock the target vnode if we're going to | ||
292 | * update its status so that stat() sees the attributes update atomically. | ||
293 | */ | ||
294 | static int yfs_decode_status(struct afs_call *call, | ||
295 | const __be32 **_bp, | ||
296 | struct afs_file_status *status, | ||
297 | struct afs_vnode *vnode, | ||
298 | const afs_dataversion_t *expected_version, | ||
299 | struct afs_read *read_req) | ||
300 | { | ||
301 | int ret; | ||
302 | |||
303 | if (!vnode) | ||
304 | return xdr_decode_YFSFetchStatus(call, _bp, status, vnode, | ||
305 | expected_version, read_req); | ||
306 | |||
307 | write_seqlock(&vnode->cb_lock); | ||
308 | ret = xdr_decode_YFSFetchStatus(call, _bp, status, vnode, | ||
309 | expected_version, read_req); | ||
310 | write_sequnlock(&vnode->cb_lock); | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | /* | ||
315 | * Decode a YFSCallBack block | ||
316 | */ | ||
317 | static void xdr_decode_YFSCallBack(struct afs_call *call, | ||
318 | struct afs_vnode *vnode, | ||
319 | const __be32 **_bp) | ||
320 | { | ||
321 | struct yfs_xdr_YFSCallBack *xdr = (void *)*_bp; | ||
322 | struct afs_cb_interest *old, *cbi = call->cbi; | ||
323 | u64 cb_expiry; | ||
324 | |||
325 | write_seqlock(&vnode->cb_lock); | ||
326 | |||
327 | if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) { | ||
328 | cb_expiry = xdr_to_u64(xdr->expiration_time); | ||
329 | do_div(cb_expiry, 10 * 1000 * 1000); | ||
330 | vnode->cb_version = ntohl(xdr->version); | ||
331 | vnode->cb_type = ntohl(xdr->type); | ||
332 | vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds(); | ||
333 | old = vnode->cb_interest; | ||
334 | if (old != call->cbi) { | ||
335 | vnode->cb_interest = cbi; | ||
336 | cbi = old; | ||
337 | } | ||
338 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
339 | } | ||
340 | |||
341 | write_sequnlock(&vnode->cb_lock); | ||
342 | call->cbi = cbi; | ||
343 | *_bp += xdr_size(xdr); | ||
344 | } | ||
345 | |||
346 | static void xdr_decode_YFSCallBack_raw(const __be32 **_bp, | ||
347 | struct afs_callback *cb) | ||
348 | { | ||
349 | struct yfs_xdr_YFSCallBack *x = (void *)*_bp; | ||
350 | u64 cb_expiry; | ||
351 | |||
352 | cb_expiry = xdr_to_u64(x->expiration_time); | ||
353 | do_div(cb_expiry, 10 * 1000 * 1000); | ||
354 | cb->version = ntohl(x->version); | ||
355 | cb->type = ntohl(x->type); | ||
356 | cb->expires_at = cb_expiry + ktime_get_real_seconds(); | ||
357 | |||
358 | *_bp += xdr_size(x); | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * Decode a YFSVolSync block | ||
363 | */ | ||
364 | static void xdr_decode_YFSVolSync(const __be32 **_bp, | ||
365 | struct afs_volsync *volsync) | ||
366 | { | ||
367 | struct yfs_xdr_YFSVolSync *x = (void *)*_bp; | ||
368 | u64 creation; | ||
369 | |||
370 | if (volsync) { | ||
371 | creation = xdr_to_u64(x->vol_creation_date); | ||
372 | do_div(creation, 10 * 1000 * 1000); | ||
373 | volsync->creation = creation; | ||
374 | } | ||
375 | |||
376 | *_bp += xdr_size(x); | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * Encode the requested attributes into a YFSStoreStatus block | ||
381 | */ | ||
382 | static __be32 *xdr_encode_YFS_StoreStatus(__be32 *bp, struct iattr *attr) | ||
383 | { | ||
384 | struct yfs_xdr_YFSStoreStatus *x = (void *)bp; | ||
385 | s64 mtime = 0, owner = 0, group = 0; | ||
386 | u32 mask = 0, mode = 0; | ||
387 | |||
388 | mask = 0; | ||
389 | if (attr->ia_valid & ATTR_MTIME) { | ||
390 | mask |= AFS_SET_MTIME; | ||
391 | mtime = linux_to_yfs_time(&attr->ia_mtime); | ||
392 | } | ||
393 | |||
394 | if (attr->ia_valid & ATTR_UID) { | ||
395 | mask |= AFS_SET_OWNER; | ||
396 | owner = from_kuid(&init_user_ns, attr->ia_uid); | ||
397 | } | ||
398 | |||
399 | if (attr->ia_valid & ATTR_GID) { | ||
400 | mask |= AFS_SET_GROUP; | ||
401 | group = from_kgid(&init_user_ns, attr->ia_gid); | ||
402 | } | ||
403 | |||
404 | if (attr->ia_valid & ATTR_MODE) { | ||
405 | mask |= AFS_SET_MODE; | ||
406 | mode = attr->ia_mode & S_IALLUGO; | ||
407 | } | ||
408 | |||
409 | x->mask = htonl(mask); | ||
410 | x->mode = htonl(mode); | ||
411 | x->mtime_client = u64_to_xdr(mtime); | ||
412 | x->owner = u64_to_xdr(owner); | ||
413 | x->group = u64_to_xdr(group); | ||
414 | return bp + xdr_size(x); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * Decode a YFSFetchVolumeStatus block. | ||
419 | */ | ||
420 | static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp, | ||
421 | struct afs_volume_status *vs) | ||
422 | { | ||
423 | const struct yfs_xdr_YFSFetchVolumeStatus *x = (const void *)*_bp; | ||
424 | u32 flags; | ||
425 | |||
426 | vs->vid = xdr_to_u64(x->vid); | ||
427 | vs->parent_id = xdr_to_u64(x->parent_id); | ||
428 | flags = ntohl(x->flags); | ||
429 | vs->online = flags & yfs_FVSOnline; | ||
430 | vs->in_service = flags & yfs_FVSInservice; | ||
431 | vs->blessed = flags & yfs_FVSBlessed; | ||
432 | vs->needs_salvage = flags & yfs_FVSNeedsSalvage; | ||
433 | vs->type = ntohl(x->type); | ||
434 | vs->min_quota = 0; | ||
435 | vs->max_quota = xdr_to_u64(x->max_quota); | ||
436 | vs->blocks_in_use = xdr_to_u64(x->blocks_in_use); | ||
437 | vs->part_blocks_avail = xdr_to_u64(x->part_blocks_avail); | ||
438 | vs->part_max_blocks = xdr_to_u64(x->part_max_blocks); | ||
439 | vs->vol_copy_date = xdr_to_u64(x->vol_copy_date); | ||
440 | vs->vol_backup_date = xdr_to_u64(x->vol_backup_date); | ||
441 | *_bp += sizeof(*x) / sizeof(__be32); | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * deliver reply data to an FS.FetchStatus | ||
446 | */ | ||
447 | static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call) | ||
448 | { | ||
449 | struct afs_vnode *vnode = call->reply[0]; | ||
450 | const __be32 *bp; | ||
451 | int ret; | ||
452 | |||
453 | ret = afs_transfer_reply(call); | ||
454 | if (ret < 0) | ||
455 | return ret; | ||
456 | |||
457 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); | ||
458 | |||
459 | /* unmarshall the reply once we've received all of it */ | ||
460 | bp = call->buffer; | ||
461 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
462 | &call->expected_version, NULL); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | xdr_decode_YFSCallBack(call, vnode, &bp); | ||
466 | xdr_decode_YFSVolSync(&bp, call->reply[1]); | ||
467 | |||
468 | _leave(" = 0 [done]"); | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * YFS.FetchStatus operation type | ||
474 | */ | ||
475 | static const struct afs_call_type yfs_RXYFSFetchStatus_vnode = { | ||
476 | .name = "YFS.FetchStatus(vnode)", | ||
477 | .op = yfs_FS_FetchStatus, | ||
478 | .deliver = yfs_deliver_fs_fetch_status_vnode, | ||
479 | .destructor = afs_flat_call_destructor, | ||
480 | }; | ||
481 | |||
482 | /* | ||
483 | * Fetch the status information for a file. | ||
484 | */ | ||
485 | int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync, | ||
486 | bool new_inode) | ||
487 | { | ||
488 | struct afs_vnode *vnode = fc->vnode; | ||
489 | struct afs_call *call; | ||
490 | struct afs_net *net = afs_v2net(vnode); | ||
491 | __be32 *bp; | ||
492 | |||
493 | _enter(",%x,{%llx:%llu},,", | ||
494 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | ||
495 | |||
496 | call = afs_alloc_flat_call(net, &yfs_RXYFSFetchStatus_vnode, | ||
497 | sizeof(__be32) * 2 + | ||
498 | sizeof(struct yfs_xdr_YFSFid), | ||
499 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
500 | sizeof(struct yfs_xdr_YFSCallBack) + | ||
501 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
502 | if (!call) { | ||
503 | fc->ac.error = -ENOMEM; | ||
504 | return -ENOMEM; | ||
505 | } | ||
506 | |||
507 | call->key = fc->key; | ||
508 | call->reply[0] = vnode; | ||
509 | call->reply[1] = volsync; | ||
510 | call->expected_version = new_inode ? 1 : vnode->status.data_version; | ||
511 | |||
512 | /* marshall the parameters */ | ||
513 | bp = call->request; | ||
514 | bp = xdr_encode_u32(bp, YFSFETCHSTATUS); | ||
515 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
516 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
517 | yfs_check_req(call, bp); | ||
518 | |||
519 | call->cb_break = fc->cb_break; | ||
520 | afs_use_fs_server(call, fc->cbi); | ||
521 | trace_afs_make_fs_call(call, &vnode->fid); | ||
522 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * Deliver reply data to an YFS.FetchData64. | ||
527 | */ | ||
528 | static int yfs_deliver_fs_fetch_data64(struct afs_call *call) | ||
529 | { | ||
530 | struct afs_vnode *vnode = call->reply[0]; | ||
531 | struct afs_read *req = call->reply[2]; | ||
532 | const __be32 *bp; | ||
533 | unsigned int size; | ||
534 | int ret; | ||
535 | |||
536 | _enter("{%u,%zu/%llu}", | ||
537 | call->unmarshall, iov_iter_count(&call->iter), req->actual_len); | ||
538 | |||
539 | switch (call->unmarshall) { | ||
540 | case 0: | ||
541 | req->actual_len = 0; | ||
542 | req->index = 0; | ||
543 | req->offset = req->pos & (PAGE_SIZE - 1); | ||
544 | afs_extract_to_tmp64(call); | ||
545 | call->unmarshall++; | ||
546 | |||
547 | /* extract the returned data length */ | ||
548 | case 1: | ||
549 | _debug("extract data length"); | ||
550 | ret = afs_extract_data(call, true); | ||
551 | if (ret < 0) | ||
552 | return ret; | ||
553 | |||
554 | req->actual_len = be64_to_cpu(call->tmp64); | ||
555 | _debug("DATA length: %llu", req->actual_len); | ||
556 | req->remain = min(req->len, req->actual_len); | ||
557 | if (req->remain == 0) | ||
558 | goto no_more_data; | ||
559 | |||
560 | call->unmarshall++; | ||
561 | |||
562 | begin_page: | ||
563 | ASSERTCMP(req->index, <, req->nr_pages); | ||
564 | if (req->remain > PAGE_SIZE - req->offset) | ||
565 | size = PAGE_SIZE - req->offset; | ||
566 | else | ||
567 | size = req->remain; | ||
568 | call->bvec[0].bv_len = size; | ||
569 | call->bvec[0].bv_offset = req->offset; | ||
570 | call->bvec[0].bv_page = req->pages[req->index]; | ||
571 | iov_iter_bvec(&call->iter, READ, call->bvec, 1, size); | ||
572 | ASSERTCMP(size, <=, PAGE_SIZE); | ||
573 | |||
574 | /* extract the returned data */ | ||
575 | case 2: | ||
576 | _debug("extract data %zu/%llu", | ||
577 | iov_iter_count(&call->iter), req->remain); | ||
578 | |||
579 | ret = afs_extract_data(call, true); | ||
580 | if (ret < 0) | ||
581 | return ret; | ||
582 | req->remain -= call->bvec[0].bv_len; | ||
583 | req->offset += call->bvec[0].bv_len; | ||
584 | ASSERTCMP(req->offset, <=, PAGE_SIZE); | ||
585 | if (req->offset == PAGE_SIZE) { | ||
586 | req->offset = 0; | ||
587 | if (req->page_done) | ||
588 | req->page_done(call, req); | ||
589 | req->index++; | ||
590 | if (req->remain > 0) | ||
591 | goto begin_page; | ||
592 | } | ||
593 | |||
594 | ASSERTCMP(req->remain, ==, 0); | ||
595 | if (req->actual_len <= req->len) | ||
596 | goto no_more_data; | ||
597 | |||
598 | /* Discard any excess data the server gave us */ | ||
599 | iov_iter_discard(&call->iter, READ, req->actual_len - req->len); | ||
600 | call->unmarshall = 3; | ||
601 | case 3: | ||
602 | _debug("extract discard %zu/%llu", | ||
603 | iov_iter_count(&call->iter), req->actual_len - req->len); | ||
604 | |||
605 | ret = afs_extract_data(call, true); | ||
606 | if (ret < 0) | ||
607 | return ret; | ||
608 | |||
609 | no_more_data: | ||
610 | call->unmarshall = 4; | ||
611 | afs_extract_to_buf(call, | ||
612 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
613 | sizeof(struct yfs_xdr_YFSCallBack) + | ||
614 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
615 | |||
616 | /* extract the metadata */ | ||
617 | case 4: | ||
618 | ret = afs_extract_data(call, false); | ||
619 | if (ret < 0) | ||
620 | return ret; | ||
621 | |||
622 | bp = call->buffer; | ||
623 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
624 | &vnode->status.data_version, req); | ||
625 | if (ret < 0) | ||
626 | return ret; | ||
627 | xdr_decode_YFSCallBack(call, vnode, &bp); | ||
628 | xdr_decode_YFSVolSync(&bp, call->reply[1]); | ||
629 | |||
630 | call->unmarshall++; | ||
631 | |||
632 | case 5: | ||
633 | break; | ||
634 | } | ||
635 | |||
636 | for (; req->index < req->nr_pages; req->index++) { | ||
637 | if (req->offset < PAGE_SIZE) | ||
638 | zero_user_segment(req->pages[req->index], | ||
639 | req->offset, PAGE_SIZE); | ||
640 | if (req->page_done) | ||
641 | req->page_done(call, req); | ||
642 | req->offset = 0; | ||
643 | } | ||
644 | |||
645 | _leave(" = 0 [done]"); | ||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static void yfs_fetch_data_destructor(struct afs_call *call) | ||
650 | { | ||
651 | struct afs_read *req = call->reply[2]; | ||
652 | |||
653 | afs_put_read(req); | ||
654 | afs_flat_call_destructor(call); | ||
655 | } | ||
656 | |||
657 | /* | ||
658 | * YFS.FetchData64 operation type | ||
659 | */ | ||
660 | static const struct afs_call_type yfs_RXYFSFetchData64 = { | ||
661 | .name = "YFS.FetchData64", | ||
662 | .op = yfs_FS_FetchData64, | ||
663 | .deliver = yfs_deliver_fs_fetch_data64, | ||
664 | .destructor = yfs_fetch_data_destructor, | ||
665 | }; | ||
666 | |||
667 | /* | ||
668 | * Fetch data from a file. | ||
669 | */ | ||
670 | int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | ||
671 | { | ||
672 | struct afs_vnode *vnode = fc->vnode; | ||
673 | struct afs_call *call; | ||
674 | struct afs_net *net = afs_v2net(vnode); | ||
675 | __be32 *bp; | ||
676 | |||
677 | _enter(",%x,{%llx:%llu},%llx,%llx", | ||
678 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode, | ||
679 | req->pos, req->len); | ||
680 | |||
681 | call = afs_alloc_flat_call(net, &yfs_RXYFSFetchData64, | ||
682 | sizeof(__be32) * 2 + | ||
683 | sizeof(struct yfs_xdr_YFSFid) + | ||
684 | sizeof(struct yfs_xdr_u64) * 2, | ||
685 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
686 | sizeof(struct yfs_xdr_YFSCallBack) + | ||
687 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
688 | if (!call) | ||
689 | return -ENOMEM; | ||
690 | |||
691 | call->key = fc->key; | ||
692 | call->reply[0] = vnode; | ||
693 | call->reply[1] = NULL; /* volsync */ | ||
694 | call->reply[2] = req; | ||
695 | call->expected_version = vnode->status.data_version; | ||
696 | call->want_reply_time = true; | ||
697 | |||
698 | /* marshall the parameters */ | ||
699 | bp = call->request; | ||
700 | bp = xdr_encode_u32(bp, YFSFETCHDATA64); | ||
701 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
702 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
703 | bp = xdr_encode_u64(bp, req->pos); | ||
704 | bp = xdr_encode_u64(bp, req->len); | ||
705 | yfs_check_req(call, bp); | ||
706 | |||
707 | refcount_inc(&req->usage); | ||
708 | call->cb_break = fc->cb_break; | ||
709 | afs_use_fs_server(call, fc->cbi); | ||
710 | trace_afs_make_fs_call(call, &vnode->fid); | ||
711 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
712 | } | ||
713 | |||
714 | /* | ||
715 | * Deliver reply data for YFS.CreateFile or YFS.MakeDir. | ||
716 | */ | ||
717 | static int yfs_deliver_fs_create_vnode(struct afs_call *call) | ||
718 | { | ||
719 | struct afs_vnode *vnode = call->reply[0]; | ||
720 | const __be32 *bp; | ||
721 | int ret; | ||
722 | |||
723 | _enter("{%u}", call->unmarshall); | ||
724 | |||
725 | ret = afs_transfer_reply(call); | ||
726 | if (ret < 0) | ||
727 | return ret; | ||
728 | |||
729 | /* unmarshall the reply once we've received all of it */ | ||
730 | bp = call->buffer; | ||
731 | xdr_decode_YFSFid(&bp, call->reply[1]); | ||
732 | ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); | ||
733 | if (ret < 0) | ||
734 | return ret; | ||
735 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
736 | &call->expected_version, NULL); | ||
737 | if (ret < 0) | ||
738 | return ret; | ||
739 | xdr_decode_YFSCallBack_raw(&bp, call->reply[3]); | ||
740 | xdr_decode_YFSVolSync(&bp, NULL); | ||
741 | |||
742 | _leave(" = 0 [done]"); | ||
743 | return 0; | ||
744 | } | ||
745 | |||
746 | /* | ||
747 | * FS.CreateFile and FS.MakeDir operation type | ||
748 | */ | ||
749 | static const struct afs_call_type afs_RXFSCreateFile = { | ||
750 | .name = "YFS.CreateFile", | ||
751 | .op = yfs_FS_CreateFile, | ||
752 | .deliver = yfs_deliver_fs_create_vnode, | ||
753 | .destructor = afs_flat_call_destructor, | ||
754 | }; | ||
755 | |||
756 | /* | ||
757 | * Create a file. | ||
758 | */ | ||
759 | int yfs_fs_create_file(struct afs_fs_cursor *fc, | ||
760 | const char *name, | ||
761 | umode_t mode, | ||
762 | u64 current_data_version, | ||
763 | struct afs_fid *newfid, | ||
764 | struct afs_file_status *newstatus, | ||
765 | struct afs_callback *newcb) | ||
766 | { | ||
767 | struct afs_vnode *vnode = fc->vnode; | ||
768 | struct afs_call *call; | ||
769 | struct afs_net *net = afs_v2net(vnode); | ||
770 | size_t namesz, reqsz, rplsz; | ||
771 | __be32 *bp; | ||
772 | |||
773 | _enter(""); | ||
774 | |||
775 | namesz = strlen(name); | ||
776 | reqsz = (sizeof(__be32) + | ||
777 | sizeof(__be32) + | ||
778 | sizeof(struct yfs_xdr_YFSFid) + | ||
779 | xdr_strlen(namesz) + | ||
780 | sizeof(struct yfs_xdr_YFSStoreStatus) + | ||
781 | sizeof(__be32)); | ||
782 | rplsz = (sizeof(struct yfs_xdr_YFSFid) + | ||
783 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
784 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
785 | sizeof(struct yfs_xdr_YFSCallBack) + | ||
786 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
787 | |||
788 | call = afs_alloc_flat_call(net, &afs_RXFSCreateFile, reqsz, rplsz); | ||
789 | if (!call) | ||
790 | return -ENOMEM; | ||
791 | |||
792 | call->key = fc->key; | ||
793 | call->reply[0] = vnode; | ||
794 | call->reply[1] = newfid; | ||
795 | call->reply[2] = newstatus; | ||
796 | call->reply[3] = newcb; | ||
797 | call->expected_version = current_data_version + 1; | ||
798 | |||
799 | /* marshall the parameters */ | ||
800 | bp = call->request; | ||
801 | bp = xdr_encode_u32(bp, YFSCREATEFILE); | ||
802 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
803 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
804 | bp = xdr_encode_string(bp, name, namesz); | ||
805 | bp = xdr_encode_YFSStoreStatus_mode(bp, mode); | ||
806 | bp = xdr_encode_u32(bp, 0); /* ViceLockType */ | ||
807 | yfs_check_req(call, bp); | ||
808 | |||
809 | afs_use_fs_server(call, fc->cbi); | ||
810 | trace_afs_make_fs_call(call, &vnode->fid); | ||
811 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
812 | } | ||
813 | |||
814 | static const struct afs_call_type yfs_RXFSMakeDir = { | ||
815 | .name = "YFS.MakeDir", | ||
816 | .op = yfs_FS_MakeDir, | ||
817 | .deliver = yfs_deliver_fs_create_vnode, | ||
818 | .destructor = afs_flat_call_destructor, | ||
819 | }; | ||
820 | |||
821 | /* | ||
822 | * Make a directory. | ||
823 | */ | ||
824 | int yfs_fs_make_dir(struct afs_fs_cursor *fc, | ||
825 | const char *name, | ||
826 | umode_t mode, | ||
827 | u64 current_data_version, | ||
828 | struct afs_fid *newfid, | ||
829 | struct afs_file_status *newstatus, | ||
830 | struct afs_callback *newcb) | ||
831 | { | ||
832 | struct afs_vnode *vnode = fc->vnode; | ||
833 | struct afs_call *call; | ||
834 | struct afs_net *net = afs_v2net(vnode); | ||
835 | size_t namesz, reqsz, rplsz; | ||
836 | __be32 *bp; | ||
837 | |||
838 | _enter(""); | ||
839 | |||
840 | namesz = strlen(name); | ||
841 | reqsz = (sizeof(__be32) + | ||
842 | sizeof(struct yfs_xdr_RPCFlags) + | ||
843 | sizeof(struct yfs_xdr_YFSFid) + | ||
844 | xdr_strlen(namesz) + | ||
845 | sizeof(struct yfs_xdr_YFSStoreStatus)); | ||
846 | rplsz = (sizeof(struct yfs_xdr_YFSFid) + | ||
847 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
848 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
849 | sizeof(struct yfs_xdr_YFSCallBack) + | ||
850 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
851 | |||
852 | call = afs_alloc_flat_call(net, &yfs_RXFSMakeDir, reqsz, rplsz); | ||
853 | if (!call) | ||
854 | return -ENOMEM; | ||
855 | |||
856 | call->key = fc->key; | ||
857 | call->reply[0] = vnode; | ||
858 | call->reply[1] = newfid; | ||
859 | call->reply[2] = newstatus; | ||
860 | call->reply[3] = newcb; | ||
861 | call->expected_version = current_data_version + 1; | ||
862 | |||
863 | /* marshall the parameters */ | ||
864 | bp = call->request; | ||
865 | bp = xdr_encode_u32(bp, YFSMAKEDIR); | ||
866 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
867 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
868 | bp = xdr_encode_string(bp, name, namesz); | ||
869 | bp = xdr_encode_YFSStoreStatus_mode(bp, mode); | ||
870 | yfs_check_req(call, bp); | ||
871 | |||
872 | afs_use_fs_server(call, fc->cbi); | ||
873 | trace_afs_make_fs_call(call, &vnode->fid); | ||
874 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
875 | } | ||
876 | |||
877 | /* | ||
878 | * Deliver reply data to a YFS.RemoveFile2 operation. | ||
879 | */ | ||
880 | static int yfs_deliver_fs_remove_file2(struct afs_call *call) | ||
881 | { | ||
882 | struct afs_vnode *dvnode = call->reply[0]; | ||
883 | struct afs_vnode *vnode = call->reply[1]; | ||
884 | struct afs_fid fid; | ||
885 | const __be32 *bp; | ||
886 | int ret; | ||
887 | |||
888 | _enter("{%u}", call->unmarshall); | ||
889 | |||
890 | ret = afs_transfer_reply(call); | ||
891 | if (ret < 0) | ||
892 | return ret; | ||
893 | |||
894 | /* unmarshall the reply once we've received all of it */ | ||
895 | bp = call->buffer; | ||
896 | ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode, | ||
897 | &call->expected_version, NULL); | ||
898 | if (ret < 0) | ||
899 | return ret; | ||
900 | |||
901 | xdr_decode_YFSFid(&bp, &fid); | ||
902 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL); | ||
903 | if (ret < 0) | ||
904 | return ret; | ||
905 | /* Was deleted if vnode->status.abort_code == VNOVNODE. */ | ||
906 | |||
907 | xdr_decode_YFSVolSync(&bp, NULL); | ||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | /* | ||
912 | * YFS.RemoveFile2 operation type. | ||
913 | */ | ||
914 | static const struct afs_call_type yfs_RXYFSRemoveFile2 = { | ||
915 | .name = "YFS.RemoveFile2", | ||
916 | .op = yfs_FS_RemoveFile2, | ||
917 | .deliver = yfs_deliver_fs_remove_file2, | ||
918 | .destructor = afs_flat_call_destructor, | ||
919 | }; | ||
920 | |||
921 | /* | ||
922 | * Remove a file and retrieve new file status. | ||
923 | */ | ||
924 | int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | ||
925 | const char *name, u64 current_data_version) | ||
926 | { | ||
927 | struct afs_vnode *dvnode = fc->vnode; | ||
928 | struct afs_call *call; | ||
929 | struct afs_net *net = afs_v2net(dvnode); | ||
930 | size_t namesz; | ||
931 | __be32 *bp; | ||
932 | |||
933 | _enter(""); | ||
934 | |||
935 | namesz = strlen(name); | ||
936 | |||
937 | call = afs_alloc_flat_call(net, &yfs_RXYFSRemoveFile2, | ||
938 | sizeof(__be32) + | ||
939 | sizeof(struct yfs_xdr_RPCFlags) + | ||
940 | sizeof(struct yfs_xdr_YFSFid) + | ||
941 | xdr_strlen(namesz), | ||
942 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
943 | sizeof(struct yfs_xdr_YFSFid) + | ||
944 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
945 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
946 | if (!call) | ||
947 | return -ENOMEM; | ||
948 | |||
949 | call->key = fc->key; | ||
950 | call->reply[0] = dvnode; | ||
951 | call->reply[1] = vnode; | ||
952 | call->expected_version = current_data_version + 1; | ||
953 | |||
954 | /* marshall the parameters */ | ||
955 | bp = call->request; | ||
956 | bp = xdr_encode_u32(bp, YFSREMOVEFILE2); | ||
957 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
958 | bp = xdr_encode_YFSFid(bp, &dvnode->fid); | ||
959 | bp = xdr_encode_string(bp, name, namesz); | ||
960 | yfs_check_req(call, bp); | ||
961 | |||
962 | afs_use_fs_server(call, fc->cbi); | ||
963 | trace_afs_make_fs_call(call, &dvnode->fid); | ||
964 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
965 | } | ||
966 | |||
967 | /* | ||
968 | * Deliver reply data to a YFS.RemoveFile or YFS.RemoveDir operation. | ||
969 | */ | ||
970 | static int yfs_deliver_fs_remove(struct afs_call *call) | ||
971 | { | ||
972 | struct afs_vnode *dvnode = call->reply[0]; | ||
973 | const __be32 *bp; | ||
974 | int ret; | ||
975 | |||
976 | _enter("{%u}", call->unmarshall); | ||
977 | |||
978 | ret = afs_transfer_reply(call); | ||
979 | if (ret < 0) | ||
980 | return ret; | ||
981 | |||
982 | /* unmarshall the reply once we've received all of it */ | ||
983 | bp = call->buffer; | ||
984 | ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode, | ||
985 | &call->expected_version, NULL); | ||
986 | if (ret < 0) | ||
987 | return ret; | ||
988 | |||
989 | xdr_decode_YFSVolSync(&bp, NULL); | ||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | /* | ||
994 | * FS.RemoveDir and FS.RemoveFile operation types. | ||
995 | */ | ||
996 | static const struct afs_call_type yfs_RXYFSRemoveFile = { | ||
997 | .name = "YFS.RemoveFile", | ||
998 | .op = yfs_FS_RemoveFile, | ||
999 | .deliver = yfs_deliver_fs_remove, | ||
1000 | .destructor = afs_flat_call_destructor, | ||
1001 | }; | ||
1002 | |||
1003 | static const struct afs_call_type yfs_RXYFSRemoveDir = { | ||
1004 | .name = "YFS.RemoveDir", | ||
1005 | .op = yfs_FS_RemoveDir, | ||
1006 | .deliver = yfs_deliver_fs_remove, | ||
1007 | .destructor = afs_flat_call_destructor, | ||
1008 | }; | ||
1009 | |||
1010 | /* | ||
1011 | * remove a file or directory | ||
1012 | */ | ||
1013 | int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | ||
1014 | const char *name, bool isdir, u64 current_data_version) | ||
1015 | { | ||
1016 | struct afs_vnode *dvnode = fc->vnode; | ||
1017 | struct afs_call *call; | ||
1018 | struct afs_net *net = afs_v2net(dvnode); | ||
1019 | size_t namesz; | ||
1020 | __be32 *bp; | ||
1021 | |||
1022 | _enter(""); | ||
1023 | |||
1024 | namesz = strlen(name); | ||
1025 | call = afs_alloc_flat_call( | ||
1026 | net, isdir ? &yfs_RXYFSRemoveDir : &yfs_RXYFSRemoveFile, | ||
1027 | sizeof(__be32) + | ||
1028 | sizeof(struct yfs_xdr_RPCFlags) + | ||
1029 | sizeof(struct yfs_xdr_YFSFid) + | ||
1030 | xdr_strlen(namesz), | ||
1031 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1032 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1033 | if (!call) | ||
1034 | return -ENOMEM; | ||
1035 | |||
1036 | call->key = fc->key; | ||
1037 | call->reply[0] = dvnode; | ||
1038 | call->reply[1] = vnode; | ||
1039 | call->expected_version = current_data_version + 1; | ||
1040 | |||
1041 | /* marshall the parameters */ | ||
1042 | bp = call->request; | ||
1043 | bp = xdr_encode_u32(bp, isdir ? YFSREMOVEDIR : YFSREMOVEFILE); | ||
1044 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1045 | bp = xdr_encode_YFSFid(bp, &dvnode->fid); | ||
1046 | bp = xdr_encode_string(bp, name, namesz); | ||
1047 | yfs_check_req(call, bp); | ||
1048 | |||
1049 | afs_use_fs_server(call, fc->cbi); | ||
1050 | trace_afs_make_fs_call(call, &dvnode->fid); | ||
1051 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1052 | } | ||
1053 | |||
1054 | /* | ||
1055 | * Deliver reply data to a YFS.Link operation. | ||
1056 | */ | ||
1057 | static int yfs_deliver_fs_link(struct afs_call *call) | ||
1058 | { | ||
1059 | struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1]; | ||
1060 | const __be32 *bp; | ||
1061 | int ret; | ||
1062 | |||
1063 | _enter("{%u}", call->unmarshall); | ||
1064 | |||
1065 | ret = afs_transfer_reply(call); | ||
1066 | if (ret < 0) | ||
1067 | return ret; | ||
1068 | |||
1069 | /* unmarshall the reply once we've received all of it */ | ||
1070 | bp = call->buffer; | ||
1071 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL); | ||
1072 | if (ret < 0) | ||
1073 | return ret; | ||
1074 | ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode, | ||
1075 | &call->expected_version, NULL); | ||
1076 | if (ret < 0) | ||
1077 | return ret; | ||
1078 | xdr_decode_YFSVolSync(&bp, NULL); | ||
1079 | _leave(" = 0 [done]"); | ||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | /* | ||
1084 | * YFS.Link operation type. | ||
1085 | */ | ||
1086 | static const struct afs_call_type yfs_RXYFSLink = { | ||
1087 | .name = "YFS.Link", | ||
1088 | .op = yfs_FS_Link, | ||
1089 | .deliver = yfs_deliver_fs_link, | ||
1090 | .destructor = afs_flat_call_destructor, | ||
1091 | }; | ||
1092 | |||
1093 | /* | ||
1094 | * Make a hard link. | ||
1095 | */ | ||
1096 | int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | ||
1097 | const char *name, u64 current_data_version) | ||
1098 | { | ||
1099 | struct afs_vnode *dvnode = fc->vnode; | ||
1100 | struct afs_call *call; | ||
1101 | struct afs_net *net = afs_v2net(vnode); | ||
1102 | size_t namesz; | ||
1103 | __be32 *bp; | ||
1104 | |||
1105 | _enter(""); | ||
1106 | |||
1107 | namesz = strlen(name); | ||
1108 | call = afs_alloc_flat_call(net, &yfs_RXYFSLink, | ||
1109 | sizeof(__be32) + | ||
1110 | sizeof(struct yfs_xdr_RPCFlags) + | ||
1111 | sizeof(struct yfs_xdr_YFSFid) + | ||
1112 | xdr_strlen(namesz) + | ||
1113 | sizeof(struct yfs_xdr_YFSFid), | ||
1114 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1115 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1116 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1117 | if (!call) | ||
1118 | return -ENOMEM; | ||
1119 | |||
1120 | call->key = fc->key; | ||
1121 | call->reply[0] = dvnode; | ||
1122 | call->reply[1] = vnode; | ||
1123 | call->expected_version = current_data_version + 1; | ||
1124 | |||
1125 | /* marshall the parameters */ | ||
1126 | bp = call->request; | ||
1127 | bp = xdr_encode_u32(bp, YFSLINK); | ||
1128 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1129 | bp = xdr_encode_YFSFid(bp, &dvnode->fid); | ||
1130 | bp = xdr_encode_string(bp, name, namesz); | ||
1131 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
1132 | yfs_check_req(call, bp); | ||
1133 | |||
1134 | afs_use_fs_server(call, fc->cbi); | ||
1135 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1136 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1137 | } | ||
1138 | |||
1139 | /* | ||
1140 | * Deliver reply data to a YFS.Symlink operation. | ||
1141 | */ | ||
1142 | static int yfs_deliver_fs_symlink(struct afs_call *call) | ||
1143 | { | ||
1144 | struct afs_vnode *vnode = call->reply[0]; | ||
1145 | const __be32 *bp; | ||
1146 | int ret; | ||
1147 | |||
1148 | _enter("{%u}", call->unmarshall); | ||
1149 | |||
1150 | ret = afs_transfer_reply(call); | ||
1151 | if (ret < 0) | ||
1152 | return ret; | ||
1153 | |||
1154 | /* unmarshall the reply once we've received all of it */ | ||
1155 | bp = call->buffer; | ||
1156 | xdr_decode_YFSFid(&bp, call->reply[1]); | ||
1157 | ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); | ||
1158 | if (ret < 0) | ||
1159 | return ret; | ||
1160 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
1161 | &call->expected_version, NULL); | ||
1162 | if (ret < 0) | ||
1163 | return ret; | ||
1164 | xdr_decode_YFSVolSync(&bp, NULL); | ||
1165 | |||
1166 | _leave(" = 0 [done]"); | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | /* | ||
1171 | * YFS.Symlink operation type | ||
1172 | */ | ||
1173 | static const struct afs_call_type yfs_RXYFSSymlink = { | ||
1174 | .name = "YFS.Symlink", | ||
1175 | .op = yfs_FS_Symlink, | ||
1176 | .deliver = yfs_deliver_fs_symlink, | ||
1177 | .destructor = afs_flat_call_destructor, | ||
1178 | }; | ||
1179 | |||
1180 | /* | ||
1181 | * Create a symbolic link. | ||
1182 | */ | ||
1183 | int yfs_fs_symlink(struct afs_fs_cursor *fc, | ||
1184 | const char *name, | ||
1185 | const char *contents, | ||
1186 | u64 current_data_version, | ||
1187 | struct afs_fid *newfid, | ||
1188 | struct afs_file_status *newstatus) | ||
1189 | { | ||
1190 | struct afs_vnode *dvnode = fc->vnode; | ||
1191 | struct afs_call *call; | ||
1192 | struct afs_net *net = afs_v2net(dvnode); | ||
1193 | size_t namesz, contents_sz; | ||
1194 | __be32 *bp; | ||
1195 | |||
1196 | _enter(""); | ||
1197 | |||
1198 | namesz = strlen(name); | ||
1199 | contents_sz = strlen(contents); | ||
1200 | call = afs_alloc_flat_call(net, &yfs_RXYFSSymlink, | ||
1201 | sizeof(__be32) + | ||
1202 | sizeof(struct yfs_xdr_RPCFlags) + | ||
1203 | sizeof(struct yfs_xdr_YFSFid) + | ||
1204 | xdr_strlen(namesz) + | ||
1205 | xdr_strlen(contents_sz) + | ||
1206 | sizeof(struct yfs_xdr_YFSStoreStatus), | ||
1207 | sizeof(struct yfs_xdr_YFSFid) + | ||
1208 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1209 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1210 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1211 | if (!call) | ||
1212 | return -ENOMEM; | ||
1213 | |||
1214 | call->key = fc->key; | ||
1215 | call->reply[0] = dvnode; | ||
1216 | call->reply[1] = newfid; | ||
1217 | call->reply[2] = newstatus; | ||
1218 | call->expected_version = current_data_version + 1; | ||
1219 | |||
1220 | /* marshall the parameters */ | ||
1221 | bp = call->request; | ||
1222 | bp = xdr_encode_u32(bp, YFSSYMLINK); | ||
1223 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1224 | bp = xdr_encode_YFSFid(bp, &dvnode->fid); | ||
1225 | bp = xdr_encode_string(bp, name, namesz); | ||
1226 | bp = xdr_encode_string(bp, contents, contents_sz); | ||
1227 | bp = xdr_encode_YFSStoreStatus_mode(bp, S_IRWXUGO); | ||
1228 | yfs_check_req(call, bp); | ||
1229 | |||
1230 | afs_use_fs_server(call, fc->cbi); | ||
1231 | trace_afs_make_fs_call(call, &dvnode->fid); | ||
1232 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1233 | } | ||
1234 | |||
1235 | /* | ||
1236 | * Deliver reply data to a YFS.Rename operation. | ||
1237 | */ | ||
1238 | static int yfs_deliver_fs_rename(struct afs_call *call) | ||
1239 | { | ||
1240 | struct afs_vnode *orig_dvnode = call->reply[0]; | ||
1241 | struct afs_vnode *new_dvnode = call->reply[1]; | ||
1242 | const __be32 *bp; | ||
1243 | int ret; | ||
1244 | |||
1245 | _enter("{%u}", call->unmarshall); | ||
1246 | |||
1247 | ret = afs_transfer_reply(call); | ||
1248 | if (ret < 0) | ||
1249 | return ret; | ||
1250 | |||
1251 | /* unmarshall the reply once we've received all of it */ | ||
1252 | bp = call->buffer; | ||
1253 | ret = yfs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode, | ||
1254 | &call->expected_version, NULL); | ||
1255 | if (ret < 0) | ||
1256 | return ret; | ||
1257 | if (new_dvnode != orig_dvnode) { | ||
1258 | ret = yfs_decode_status(call, &bp, &new_dvnode->status, new_dvnode, | ||
1259 | &call->expected_version_2, NULL); | ||
1260 | if (ret < 0) | ||
1261 | return ret; | ||
1262 | } | ||
1263 | |||
1264 | xdr_decode_YFSVolSync(&bp, NULL); | ||
1265 | _leave(" = 0 [done]"); | ||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | /* | ||
1270 | * YFS.Rename operation type | ||
1271 | */ | ||
1272 | static const struct afs_call_type yfs_RXYFSRename = { | ||
1273 | .name = "FS.Rename", | ||
1274 | .op = yfs_FS_Rename, | ||
1275 | .deliver = yfs_deliver_fs_rename, | ||
1276 | .destructor = afs_flat_call_destructor, | ||
1277 | }; | ||
1278 | |||
1279 | /* | ||
1280 | * Rename a file or directory. | ||
1281 | */ | ||
1282 | int yfs_fs_rename(struct afs_fs_cursor *fc, | ||
1283 | const char *orig_name, | ||
1284 | struct afs_vnode *new_dvnode, | ||
1285 | const char *new_name, | ||
1286 | u64 current_orig_data_version, | ||
1287 | u64 current_new_data_version) | ||
1288 | { | ||
1289 | struct afs_vnode *orig_dvnode = fc->vnode; | ||
1290 | struct afs_call *call; | ||
1291 | struct afs_net *net = afs_v2net(orig_dvnode); | ||
1292 | size_t o_namesz, n_namesz; | ||
1293 | __be32 *bp; | ||
1294 | |||
1295 | _enter(""); | ||
1296 | |||
1297 | o_namesz = strlen(orig_name); | ||
1298 | n_namesz = strlen(new_name); | ||
1299 | call = afs_alloc_flat_call(net, &yfs_RXYFSRename, | ||
1300 | sizeof(__be32) + | ||
1301 | sizeof(struct yfs_xdr_RPCFlags) + | ||
1302 | sizeof(struct yfs_xdr_YFSFid) + | ||
1303 | xdr_strlen(o_namesz) + | ||
1304 | sizeof(struct yfs_xdr_YFSFid) + | ||
1305 | xdr_strlen(n_namesz), | ||
1306 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1307 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1308 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1309 | if (!call) | ||
1310 | return -ENOMEM; | ||
1311 | |||
1312 | call->key = fc->key; | ||
1313 | call->reply[0] = orig_dvnode; | ||
1314 | call->reply[1] = new_dvnode; | ||
1315 | call->expected_version = current_orig_data_version + 1; | ||
1316 | call->expected_version_2 = current_new_data_version + 1; | ||
1317 | |||
1318 | /* marshall the parameters */ | ||
1319 | bp = call->request; | ||
1320 | bp = xdr_encode_u32(bp, YFSRENAME); | ||
1321 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1322 | bp = xdr_encode_YFSFid(bp, &orig_dvnode->fid); | ||
1323 | bp = xdr_encode_string(bp, orig_name, o_namesz); | ||
1324 | bp = xdr_encode_YFSFid(bp, &new_dvnode->fid); | ||
1325 | bp = xdr_encode_string(bp, new_name, n_namesz); | ||
1326 | yfs_check_req(call, bp); | ||
1327 | |||
1328 | afs_use_fs_server(call, fc->cbi); | ||
1329 | trace_afs_make_fs_call(call, &orig_dvnode->fid); | ||
1330 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1331 | } | ||
1332 | |||
1333 | /* | ||
1334 | * Deliver reply data to a YFS.StoreData64 operation. | ||
1335 | */ | ||
1336 | static int yfs_deliver_fs_store_data(struct afs_call *call) | ||
1337 | { | ||
1338 | struct afs_vnode *vnode = call->reply[0]; | ||
1339 | const __be32 *bp; | ||
1340 | int ret; | ||
1341 | |||
1342 | _enter(""); | ||
1343 | |||
1344 | ret = afs_transfer_reply(call); | ||
1345 | if (ret < 0) | ||
1346 | return ret; | ||
1347 | |||
1348 | /* unmarshall the reply once we've received all of it */ | ||
1349 | bp = call->buffer; | ||
1350 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
1351 | &call->expected_version, NULL); | ||
1352 | if (ret < 0) | ||
1353 | return ret; | ||
1354 | xdr_decode_YFSVolSync(&bp, NULL); | ||
1355 | |||
1356 | afs_pages_written_back(vnode, call); | ||
1357 | |||
1358 | _leave(" = 0 [done]"); | ||
1359 | return 0; | ||
1360 | } | ||
1361 | |||
1362 | /* | ||
1363 | * YFS.StoreData64 operation type. | ||
1364 | */ | ||
1365 | static const struct afs_call_type yfs_RXYFSStoreData64 = { | ||
1366 | .name = "YFS.StoreData64", | ||
1367 | .op = yfs_FS_StoreData64, | ||
1368 | .deliver = yfs_deliver_fs_store_data, | ||
1369 | .destructor = afs_flat_call_destructor, | ||
1370 | }; | ||
1371 | |||
1372 | /* | ||
1373 | * Store a set of pages to a large file. | ||
1374 | */ | ||
1375 | int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | ||
1376 | pgoff_t first, pgoff_t last, | ||
1377 | unsigned offset, unsigned to) | ||
1378 | { | ||
1379 | struct afs_vnode *vnode = fc->vnode; | ||
1380 | struct afs_call *call; | ||
1381 | struct afs_net *net = afs_v2net(vnode); | ||
1382 | loff_t size, pos, i_size; | ||
1383 | __be32 *bp; | ||
1384 | |||
1385 | _enter(",%x,{%llx:%llu},,", | ||
1386 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | ||
1387 | |||
1388 | size = (loff_t)to - (loff_t)offset; | ||
1389 | if (first != last) | ||
1390 | size += (loff_t)(last - first) << PAGE_SHIFT; | ||
1391 | pos = (loff_t)first << PAGE_SHIFT; | ||
1392 | pos += offset; | ||
1393 | |||
1394 | i_size = i_size_read(&vnode->vfs_inode); | ||
1395 | if (pos + size > i_size) | ||
1396 | i_size = size + pos; | ||
1397 | |||
1398 | _debug("size %llx, at %llx, i_size %llx", | ||
1399 | (unsigned long long)size, (unsigned long long)pos, | ||
1400 | (unsigned long long)i_size); | ||
1401 | |||
1402 | call = afs_alloc_flat_call(net, &yfs_RXYFSStoreData64, | ||
1403 | sizeof(__be32) + | ||
1404 | sizeof(__be32) + | ||
1405 | sizeof(struct yfs_xdr_YFSFid) + | ||
1406 | sizeof(struct yfs_xdr_YFSStoreStatus) + | ||
1407 | sizeof(struct yfs_xdr_u64) * 3, | ||
1408 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1409 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1410 | if (!call) | ||
1411 | return -ENOMEM; | ||
1412 | |||
1413 | call->key = fc->key; | ||
1414 | call->mapping = mapping; | ||
1415 | call->reply[0] = vnode; | ||
1416 | call->first = first; | ||
1417 | call->last = last; | ||
1418 | call->first_offset = offset; | ||
1419 | call->last_to = to; | ||
1420 | call->send_pages = true; | ||
1421 | call->expected_version = vnode->status.data_version + 1; | ||
1422 | |||
1423 | /* marshall the parameters */ | ||
1424 | bp = call->request; | ||
1425 | bp = xdr_encode_u32(bp, YFSSTOREDATA64); | ||
1426 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1427 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
1428 | bp = xdr_encode_YFSStoreStatus_mtime(bp, &vnode->vfs_inode.i_mtime); | ||
1429 | bp = xdr_encode_u64(bp, pos); | ||
1430 | bp = xdr_encode_u64(bp, size); | ||
1431 | bp = xdr_encode_u64(bp, i_size); | ||
1432 | yfs_check_req(call, bp); | ||
1433 | |||
1434 | afs_use_fs_server(call, fc->cbi); | ||
1435 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1436 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1437 | } | ||
1438 | |||
1439 | /* | ||
1440 | * deliver reply data to an FS.StoreStatus | ||
1441 | */ | ||
1442 | static int yfs_deliver_fs_store_status(struct afs_call *call) | ||
1443 | { | ||
1444 | struct afs_vnode *vnode = call->reply[0]; | ||
1445 | const __be32 *bp; | ||
1446 | int ret; | ||
1447 | |||
1448 | _enter(""); | ||
1449 | |||
1450 | ret = afs_transfer_reply(call); | ||
1451 | if (ret < 0) | ||
1452 | return ret; | ||
1453 | |||
1454 | /* unmarshall the reply once we've received all of it */ | ||
1455 | bp = call->buffer; | ||
1456 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
1457 | &call->expected_version, NULL); | ||
1458 | if (ret < 0) | ||
1459 | return ret; | ||
1460 | xdr_decode_YFSVolSync(&bp, NULL); | ||
1461 | |||
1462 | _leave(" = 0 [done]"); | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1466 | /* | ||
1467 | * YFS.StoreStatus operation type | ||
1468 | */ | ||
1469 | static const struct afs_call_type yfs_RXYFSStoreStatus = { | ||
1470 | .name = "YFS.StoreStatus", | ||
1471 | .op = yfs_FS_StoreStatus, | ||
1472 | .deliver = yfs_deliver_fs_store_status, | ||
1473 | .destructor = afs_flat_call_destructor, | ||
1474 | }; | ||
1475 | |||
1476 | static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = { | ||
1477 | .name = "YFS.StoreData64", | ||
1478 | .op = yfs_FS_StoreData64, | ||
1479 | .deliver = yfs_deliver_fs_store_status, | ||
1480 | .destructor = afs_flat_call_destructor, | ||
1481 | }; | ||
1482 | |||
1483 | /* | ||
1484 | * Set the attributes on a file, using YFS.StoreData64 rather than | ||
1485 | * YFS.StoreStatus so as to alter the file size also. | ||
1486 | */ | ||
1487 | static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | ||
1488 | { | ||
1489 | struct afs_vnode *vnode = fc->vnode; | ||
1490 | struct afs_call *call; | ||
1491 | struct afs_net *net = afs_v2net(vnode); | ||
1492 | __be32 *bp; | ||
1493 | |||
1494 | _enter(",%x,{%llx:%llu},,", | ||
1495 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | ||
1496 | |||
1497 | call = afs_alloc_flat_call(net, &yfs_RXYFSStoreData64_as_Status, | ||
1498 | sizeof(__be32) * 2 + | ||
1499 | sizeof(struct yfs_xdr_YFSFid) + | ||
1500 | sizeof(struct yfs_xdr_YFSStoreStatus) + | ||
1501 | sizeof(struct yfs_xdr_u64) * 3, | ||
1502 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1503 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1504 | if (!call) | ||
1505 | return -ENOMEM; | ||
1506 | |||
1507 | call->key = fc->key; | ||
1508 | call->reply[0] = vnode; | ||
1509 | call->expected_version = vnode->status.data_version + 1; | ||
1510 | |||
1511 | /* marshall the parameters */ | ||
1512 | bp = call->request; | ||
1513 | bp = xdr_encode_u32(bp, YFSSTOREDATA64); | ||
1514 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1515 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
1516 | bp = xdr_encode_YFS_StoreStatus(bp, attr); | ||
1517 | bp = xdr_encode_u64(bp, 0); /* position of start of write */ | ||
1518 | bp = xdr_encode_u64(bp, 0); /* size of write */ | ||
1519 | bp = xdr_encode_u64(bp, attr->ia_size); /* new file length */ | ||
1520 | yfs_check_req(call, bp); | ||
1521 | |||
1522 | afs_use_fs_server(call, fc->cbi); | ||
1523 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1524 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1525 | } | ||
1526 | |||
1527 | /* | ||
1528 | * Set the attributes on a file, using YFS.StoreData64 if there's a change in | ||
1529 | * file size, and YFS.StoreStatus otherwise. | ||
1530 | */ | ||
1531 | int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | ||
1532 | { | ||
1533 | struct afs_vnode *vnode = fc->vnode; | ||
1534 | struct afs_call *call; | ||
1535 | struct afs_net *net = afs_v2net(vnode); | ||
1536 | __be32 *bp; | ||
1537 | |||
1538 | if (attr->ia_valid & ATTR_SIZE) | ||
1539 | return yfs_fs_setattr_size(fc, attr); | ||
1540 | |||
1541 | _enter(",%x,{%llx:%llu},,", | ||
1542 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | ||
1543 | |||
1544 | call = afs_alloc_flat_call(net, &yfs_RXYFSStoreStatus, | ||
1545 | sizeof(__be32) * 2 + | ||
1546 | sizeof(struct yfs_xdr_YFSFid) + | ||
1547 | sizeof(struct yfs_xdr_YFSStoreStatus), | ||
1548 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1549 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1550 | if (!call) | ||
1551 | return -ENOMEM; | ||
1552 | |||
1553 | call->key = fc->key; | ||
1554 | call->reply[0] = vnode; | ||
1555 | call->expected_version = vnode->status.data_version; | ||
1556 | |||
1557 | /* marshall the parameters */ | ||
1558 | bp = call->request; | ||
1559 | bp = xdr_encode_u32(bp, YFSSTORESTATUS); | ||
1560 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1561 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
1562 | bp = xdr_encode_YFS_StoreStatus(bp, attr); | ||
1563 | yfs_check_req(call, bp); | ||
1564 | |||
1565 | afs_use_fs_server(call, fc->cbi); | ||
1566 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1567 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1568 | } | ||
1569 | |||
1570 | /* | ||
1571 | * Deliver reply data to a YFS.GetVolumeStatus operation. | ||
1572 | */ | ||
1573 | static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | ||
1574 | { | ||
1575 | const __be32 *bp; | ||
1576 | char *p; | ||
1577 | u32 size; | ||
1578 | int ret; | ||
1579 | |||
1580 | _enter("{%u}", call->unmarshall); | ||
1581 | |||
1582 | switch (call->unmarshall) { | ||
1583 | case 0: | ||
1584 | call->unmarshall++; | ||
1585 | afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus)); | ||
1586 | |||
1587 | /* extract the returned status record */ | ||
1588 | case 1: | ||
1589 | _debug("extract status"); | ||
1590 | ret = afs_extract_data(call, true); | ||
1591 | if (ret < 0) | ||
1592 | return ret; | ||
1593 | |||
1594 | bp = call->buffer; | ||
1595 | xdr_decode_YFSFetchVolumeStatus(&bp, call->reply[1]); | ||
1596 | call->unmarshall++; | ||
1597 | afs_extract_to_tmp(call); | ||
1598 | |||
1599 | /* extract the volume name length */ | ||
1600 | case 2: | ||
1601 | ret = afs_extract_data(call, true); | ||
1602 | if (ret < 0) | ||
1603 | return ret; | ||
1604 | |||
1605 | call->count = ntohl(call->tmp); | ||
1606 | _debug("volname length: %u", call->count); | ||
1607 | if (call->count >= AFSNAMEMAX) | ||
1608 | return afs_protocol_error(call, -EBADMSG, | ||
1609 | afs_eproto_volname_len); | ||
1610 | size = (call->count + 3) & ~3; /* It's padded */ | ||
1611 | afs_extract_begin(call, call->reply[2], size); | ||
1612 | call->unmarshall++; | ||
1613 | |||
1614 | /* extract the volume name */ | ||
1615 | case 3: | ||
1616 | _debug("extract volname"); | ||
1617 | ret = afs_extract_data(call, true); | ||
1618 | if (ret < 0) | ||
1619 | return ret; | ||
1620 | |||
1621 | p = call->reply[2]; | ||
1622 | p[call->count] = 0; | ||
1623 | _debug("volname '%s'", p); | ||
1624 | afs_extract_to_tmp(call); | ||
1625 | call->unmarshall++; | ||
1626 | |||
1627 | /* extract the offline message length */ | ||
1628 | case 4: | ||
1629 | ret = afs_extract_data(call, true); | ||
1630 | if (ret < 0) | ||
1631 | return ret; | ||
1632 | |||
1633 | call->count = ntohl(call->tmp); | ||
1634 | _debug("offline msg length: %u", call->count); | ||
1635 | if (call->count >= AFSNAMEMAX) | ||
1636 | return afs_protocol_error(call, -EBADMSG, | ||
1637 | afs_eproto_offline_msg_len); | ||
1638 | size = (call->count + 3) & ~3; /* It's padded */ | ||
1639 | afs_extract_begin(call, call->reply[2], size); | ||
1640 | call->unmarshall++; | ||
1641 | |||
1642 | /* extract the offline message */ | ||
1643 | case 5: | ||
1644 | _debug("extract offline"); | ||
1645 | ret = afs_extract_data(call, true); | ||
1646 | if (ret < 0) | ||
1647 | return ret; | ||
1648 | |||
1649 | p = call->reply[2]; | ||
1650 | p[call->count] = 0; | ||
1651 | _debug("offline '%s'", p); | ||
1652 | |||
1653 | afs_extract_to_tmp(call); | ||
1654 | call->unmarshall++; | ||
1655 | |||
1656 | /* extract the message of the day length */ | ||
1657 | case 6: | ||
1658 | ret = afs_extract_data(call, true); | ||
1659 | if (ret < 0) | ||
1660 | return ret; | ||
1661 | |||
1662 | call->count = ntohl(call->tmp); | ||
1663 | _debug("motd length: %u", call->count); | ||
1664 | if (call->count >= AFSNAMEMAX) | ||
1665 | return afs_protocol_error(call, -EBADMSG, | ||
1666 | afs_eproto_motd_len); | ||
1667 | size = (call->count + 3) & ~3; /* It's padded */ | ||
1668 | afs_extract_begin(call, call->reply[2], size); | ||
1669 | call->unmarshall++; | ||
1670 | |||
1671 | /* extract the message of the day */ | ||
1672 | case 7: | ||
1673 | _debug("extract motd"); | ||
1674 | ret = afs_extract_data(call, false); | ||
1675 | if (ret < 0) | ||
1676 | return ret; | ||
1677 | |||
1678 | p = call->reply[2]; | ||
1679 | p[call->count] = 0; | ||
1680 | _debug("motd '%s'", p); | ||
1681 | |||
1682 | call->unmarshall++; | ||
1683 | |||
1684 | case 8: | ||
1685 | break; | ||
1686 | } | ||
1687 | |||
1688 | _leave(" = 0 [done]"); | ||
1689 | return 0; | ||
1690 | } | ||
1691 | |||
1692 | /* | ||
1693 | * Destroy a YFS.GetVolumeStatus call. | ||
1694 | */ | ||
1695 | static void yfs_get_volume_status_call_destructor(struct afs_call *call) | ||
1696 | { | ||
1697 | kfree(call->reply[2]); | ||
1698 | call->reply[2] = NULL; | ||
1699 | afs_flat_call_destructor(call); | ||
1700 | } | ||
1701 | |||
1702 | /* | ||
1703 | * YFS.GetVolumeStatus operation type | ||
1704 | */ | ||
1705 | static const struct afs_call_type yfs_RXYFSGetVolumeStatus = { | ||
1706 | .name = "YFS.GetVolumeStatus", | ||
1707 | .op = yfs_FS_GetVolumeStatus, | ||
1708 | .deliver = yfs_deliver_fs_get_volume_status, | ||
1709 | .destructor = yfs_get_volume_status_call_destructor, | ||
1710 | }; | ||
1711 | |||
1712 | /* | ||
1713 | * fetch the status of a volume | ||
1714 | */ | ||
1715 | int yfs_fs_get_volume_status(struct afs_fs_cursor *fc, | ||
1716 | struct afs_volume_status *vs) | ||
1717 | { | ||
1718 | struct afs_vnode *vnode = fc->vnode; | ||
1719 | struct afs_call *call; | ||
1720 | struct afs_net *net = afs_v2net(vnode); | ||
1721 | __be32 *bp; | ||
1722 | void *tmpbuf; | ||
1723 | |||
1724 | _enter(""); | ||
1725 | |||
1726 | tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL); | ||
1727 | if (!tmpbuf) | ||
1728 | return -ENOMEM; | ||
1729 | |||
1730 | call = afs_alloc_flat_call(net, &yfs_RXYFSGetVolumeStatus, | ||
1731 | sizeof(__be32) * 2 + | ||
1732 | sizeof(struct yfs_xdr_u64), | ||
1733 | sizeof(struct yfs_xdr_YFSFetchVolumeStatus) + | ||
1734 | sizeof(__be32)); | ||
1735 | if (!call) { | ||
1736 | kfree(tmpbuf); | ||
1737 | return -ENOMEM; | ||
1738 | } | ||
1739 | |||
1740 | call->key = fc->key; | ||
1741 | call->reply[0] = vnode; | ||
1742 | call->reply[1] = vs; | ||
1743 | call->reply[2] = tmpbuf; | ||
1744 | |||
1745 | /* marshall the parameters */ | ||
1746 | bp = call->request; | ||
1747 | bp = xdr_encode_u32(bp, YFSGETVOLUMESTATUS); | ||
1748 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1749 | bp = xdr_encode_u64(bp, vnode->fid.vid); | ||
1750 | yfs_check_req(call, bp); | ||
1751 | |||
1752 | afs_use_fs_server(call, fc->cbi); | ||
1753 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1754 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1755 | } | ||
1756 | |||
1757 | /* | ||
1758 | * Deliver reply data to an YFS.SetLock, YFS.ExtendLock or YFS.ReleaseLock | ||
1759 | */ | ||
1760 | static int yfs_deliver_fs_xxxx_lock(struct afs_call *call) | ||
1761 | { | ||
1762 | struct afs_vnode *vnode = call->reply[0]; | ||
1763 | const __be32 *bp; | ||
1764 | int ret; | ||
1765 | |||
1766 | _enter("{%u}", call->unmarshall); | ||
1767 | |||
1768 | ret = afs_transfer_reply(call); | ||
1769 | if (ret < 0) | ||
1770 | return ret; | ||
1771 | |||
1772 | /* unmarshall the reply once we've received all of it */ | ||
1773 | bp = call->buffer; | ||
1774 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
1775 | &call->expected_version, NULL); | ||
1776 | if (ret < 0) | ||
1777 | return ret; | ||
1778 | xdr_decode_YFSVolSync(&bp, NULL); | ||
1779 | |||
1780 | _leave(" = 0 [done]"); | ||
1781 | return 0; | ||
1782 | } | ||
1783 | |||
1784 | /* | ||
1785 | * YFS.SetLock operation type | ||
1786 | */ | ||
1787 | static const struct afs_call_type yfs_RXYFSSetLock = { | ||
1788 | .name = "YFS.SetLock", | ||
1789 | .op = yfs_FS_SetLock, | ||
1790 | .deliver = yfs_deliver_fs_xxxx_lock, | ||
1791 | .destructor = afs_flat_call_destructor, | ||
1792 | }; | ||
1793 | |||
1794 | /* | ||
1795 | * YFS.ExtendLock operation type | ||
1796 | */ | ||
1797 | static const struct afs_call_type yfs_RXYFSExtendLock = { | ||
1798 | .name = "YFS.ExtendLock", | ||
1799 | .op = yfs_FS_ExtendLock, | ||
1800 | .deliver = yfs_deliver_fs_xxxx_lock, | ||
1801 | .destructor = afs_flat_call_destructor, | ||
1802 | }; | ||
1803 | |||
1804 | /* | ||
1805 | * YFS.ReleaseLock operation type | ||
1806 | */ | ||
1807 | static const struct afs_call_type yfs_RXYFSReleaseLock = { | ||
1808 | .name = "YFS.ReleaseLock", | ||
1809 | .op = yfs_FS_ReleaseLock, | ||
1810 | .deliver = yfs_deliver_fs_xxxx_lock, | ||
1811 | .destructor = afs_flat_call_destructor, | ||
1812 | }; | ||
1813 | |||
1814 | /* | ||
1815 | * Set a lock on a file | ||
1816 | */ | ||
1817 | int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | ||
1818 | { | ||
1819 | struct afs_vnode *vnode = fc->vnode; | ||
1820 | struct afs_call *call; | ||
1821 | struct afs_net *net = afs_v2net(vnode); | ||
1822 | __be32 *bp; | ||
1823 | |||
1824 | _enter(""); | ||
1825 | |||
1826 | call = afs_alloc_flat_call(net, &yfs_RXYFSSetLock, | ||
1827 | sizeof(__be32) * 2 + | ||
1828 | sizeof(struct yfs_xdr_YFSFid) + | ||
1829 | sizeof(__be32), | ||
1830 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1831 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1832 | if (!call) | ||
1833 | return -ENOMEM; | ||
1834 | |||
1835 | call->key = fc->key; | ||
1836 | call->reply[0] = vnode; | ||
1837 | |||
1838 | /* marshall the parameters */ | ||
1839 | bp = call->request; | ||
1840 | bp = xdr_encode_u32(bp, YFSSETLOCK); | ||
1841 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1842 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
1843 | bp = xdr_encode_u32(bp, type); | ||
1844 | yfs_check_req(call, bp); | ||
1845 | |||
1846 | afs_use_fs_server(call, fc->cbi); | ||
1847 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1848 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1849 | } | ||
1850 | |||
1851 | /* | ||
1852 | * extend a lock on a file | ||
1853 | */ | ||
1854 | int yfs_fs_extend_lock(struct afs_fs_cursor *fc) | ||
1855 | { | ||
1856 | struct afs_vnode *vnode = fc->vnode; | ||
1857 | struct afs_call *call; | ||
1858 | struct afs_net *net = afs_v2net(vnode); | ||
1859 | __be32 *bp; | ||
1860 | |||
1861 | _enter(""); | ||
1862 | |||
1863 | call = afs_alloc_flat_call(net, &yfs_RXYFSExtendLock, | ||
1864 | sizeof(__be32) * 2 + | ||
1865 | sizeof(struct yfs_xdr_YFSFid), | ||
1866 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1867 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1868 | if (!call) | ||
1869 | return -ENOMEM; | ||
1870 | |||
1871 | call->key = fc->key; | ||
1872 | call->reply[0] = vnode; | ||
1873 | |||
1874 | /* marshall the parameters */ | ||
1875 | bp = call->request; | ||
1876 | bp = xdr_encode_u32(bp, YFSEXTENDLOCK); | ||
1877 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1878 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
1879 | yfs_check_req(call, bp); | ||
1880 | |||
1881 | afs_use_fs_server(call, fc->cbi); | ||
1882 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1883 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1884 | } | ||
1885 | |||
1886 | /* | ||
1887 | * release a lock on a file | ||
1888 | */ | ||
1889 | int yfs_fs_release_lock(struct afs_fs_cursor *fc) | ||
1890 | { | ||
1891 | struct afs_vnode *vnode = fc->vnode; | ||
1892 | struct afs_call *call; | ||
1893 | struct afs_net *net = afs_v2net(vnode); | ||
1894 | __be32 *bp; | ||
1895 | |||
1896 | _enter(""); | ||
1897 | |||
1898 | call = afs_alloc_flat_call(net, &yfs_RXYFSReleaseLock, | ||
1899 | sizeof(__be32) * 2 + | ||
1900 | sizeof(struct yfs_xdr_YFSFid), | ||
1901 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1902 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1903 | if (!call) | ||
1904 | return -ENOMEM; | ||
1905 | |||
1906 | call->key = fc->key; | ||
1907 | call->reply[0] = vnode; | ||
1908 | |||
1909 | /* marshall the parameters */ | ||
1910 | bp = call->request; | ||
1911 | bp = xdr_encode_u32(bp, YFSRELEASELOCK); | ||
1912 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
1913 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | ||
1914 | yfs_check_req(call, bp); | ||
1915 | |||
1916 | afs_use_fs_server(call, fc->cbi); | ||
1917 | trace_afs_make_fs_call(call, &vnode->fid); | ||
1918 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
1919 | } | ||
1920 | |||
1921 | /* | ||
1922 | * Deliver reply data to an FS.FetchStatus with no vnode. | ||
1923 | */ | ||
1924 | static int yfs_deliver_fs_fetch_status(struct afs_call *call) | ||
1925 | { | ||
1926 | struct afs_file_status *status = call->reply[1]; | ||
1927 | struct afs_callback *callback = call->reply[2]; | ||
1928 | struct afs_volsync *volsync = call->reply[3]; | ||
1929 | struct afs_vnode *vnode = call->reply[0]; | ||
1930 | const __be32 *bp; | ||
1931 | int ret; | ||
1932 | |||
1933 | ret = afs_transfer_reply(call); | ||
1934 | if (ret < 0) | ||
1935 | return ret; | ||
1936 | |||
1937 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); | ||
1938 | |||
1939 | /* unmarshall the reply once we've received all of it */ | ||
1940 | bp = call->buffer; | ||
1941 | ret = yfs_decode_status(call, &bp, status, vnode, | ||
1942 | &call->expected_version, NULL); | ||
1943 | if (ret < 0) | ||
1944 | return ret; | ||
1945 | xdr_decode_YFSCallBack_raw(&bp, callback); | ||
1946 | xdr_decode_YFSVolSync(&bp, volsync); | ||
1947 | |||
1948 | _leave(" = 0 [done]"); | ||
1949 | return 0; | ||
1950 | } | ||
1951 | |||
1952 | /* | ||
1953 | * YFS.FetchStatus operation type | ||
1954 | */ | ||
1955 | static const struct afs_call_type yfs_RXYFSFetchStatus = { | ||
1956 | .name = "YFS.FetchStatus", | ||
1957 | .op = yfs_FS_FetchStatus, | ||
1958 | .deliver = yfs_deliver_fs_fetch_status, | ||
1959 | .destructor = afs_flat_call_destructor, | ||
1960 | }; | ||
1961 | |||
1962 | /* | ||
1963 | * Fetch the status information for a fid without needing a vnode handle. | ||
1964 | */ | ||
1965 | int yfs_fs_fetch_status(struct afs_fs_cursor *fc, | ||
1966 | struct afs_net *net, | ||
1967 | struct afs_fid *fid, | ||
1968 | struct afs_file_status *status, | ||
1969 | struct afs_callback *callback, | ||
1970 | struct afs_volsync *volsync) | ||
1971 | { | ||
1972 | struct afs_call *call; | ||
1973 | __be32 *bp; | ||
1974 | |||
1975 | _enter(",%x,{%llx:%llu},,", | ||
1976 | key_serial(fc->key), fid->vid, fid->vnode); | ||
1977 | |||
1978 | call = afs_alloc_flat_call(net, &yfs_RXYFSFetchStatus, | ||
1979 | sizeof(__be32) * 2 + | ||
1980 | sizeof(struct yfs_xdr_YFSFid), | ||
1981 | sizeof(struct yfs_xdr_YFSFetchStatus) + | ||
1982 | sizeof(struct yfs_xdr_YFSCallBack) + | ||
1983 | sizeof(struct yfs_xdr_YFSVolSync)); | ||
1984 | if (!call) { | ||
1985 | fc->ac.error = -ENOMEM; | ||
1986 | return -ENOMEM; | ||
1987 | } | ||
1988 | |||
1989 | call->key = fc->key; | ||
1990 | call->reply[0] = NULL; /* vnode for fid[0] */ | ||
1991 | call->reply[1] = status; | ||
1992 | call->reply[2] = callback; | ||
1993 | call->reply[3] = volsync; | ||
1994 | call->expected_version = 1; /* vnode->status.data_version */ | ||
1995 | |||
1996 | /* marshall the parameters */ | ||
1997 | bp = call->request; | ||
1998 | bp = xdr_encode_u32(bp, YFSFETCHSTATUS); | ||
1999 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | ||
2000 | bp = xdr_encode_YFSFid(bp, fid); | ||
2001 | yfs_check_req(call, bp); | ||
2002 | |||
2003 | call->cb_break = fc->cb_break; | ||
2004 | afs_use_fs_server(call, fc->cbi); | ||
2005 | trace_afs_make_fs_call(call, fid); | ||
2006 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
2007 | } | ||
2008 | |||
2009 | /* | ||
2010 | * Deliver reply data to an YFS.InlineBulkStatus call | ||
2011 | */ | ||
2012 | static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) | ||
2013 | { | ||
2014 | struct afs_file_status *statuses; | ||
2015 | struct afs_callback *callbacks; | ||
2016 | struct afs_vnode *vnode = call->reply[0]; | ||
2017 | const __be32 *bp; | ||
2018 | u32 tmp; | ||
2019 | int ret; | ||
2020 | |||
2021 | _enter("{%u}", call->unmarshall); | ||
2022 | |||
2023 | switch (call->unmarshall) { | ||
2024 | case 0: | ||
2025 | afs_extract_to_tmp(call); | ||
2026 | call->unmarshall++; | ||
2027 | |||
2028 | /* Extract the file status count and array in two steps */ | ||
2029 | case 1: | ||
2030 | _debug("extract status count"); | ||
2031 | ret = afs_extract_data(call, true); | ||
2032 | if (ret < 0) | ||
2033 | return ret; | ||
2034 | |||
2035 | tmp = ntohl(call->tmp); | ||
2036 | _debug("status count: %u/%u", tmp, call->count2); | ||
2037 | if (tmp != call->count2) | ||
2038 | return afs_protocol_error(call, -EBADMSG, | ||
2039 | afs_eproto_ibulkst_count); | ||
2040 | |||
2041 | call->count = 0; | ||
2042 | call->unmarshall++; | ||
2043 | more_counts: | ||
2044 | afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus)); | ||
2045 | |||
2046 | case 2: | ||
2047 | _debug("extract status array %u", call->count); | ||
2048 | ret = afs_extract_data(call, true); | ||
2049 | if (ret < 0) | ||
2050 | return ret; | ||
2051 | |||
2052 | bp = call->buffer; | ||
2053 | statuses = call->reply[1]; | ||
2054 | ret = yfs_decode_status(call, &bp, &statuses[call->count], | ||
2055 | call->count == 0 ? vnode : NULL, | ||
2056 | NULL, NULL); | ||
2057 | if (ret < 0) | ||
2058 | return ret; | ||
2059 | |||
2060 | call->count++; | ||
2061 | if (call->count < call->count2) | ||
2062 | goto more_counts; | ||
2063 | |||
2064 | call->count = 0; | ||
2065 | call->unmarshall++; | ||
2066 | afs_extract_to_tmp(call); | ||
2067 | |||
2068 | /* Extract the callback count and array in two steps */ | ||
2069 | case 3: | ||
2070 | _debug("extract CB count"); | ||
2071 | ret = afs_extract_data(call, true); | ||
2072 | if (ret < 0) | ||
2073 | return ret; | ||
2074 | |||
2075 | tmp = ntohl(call->tmp); | ||
2076 | _debug("CB count: %u", tmp); | ||
2077 | if (tmp != call->count2) | ||
2078 | return afs_protocol_error(call, -EBADMSG, | ||
2079 | afs_eproto_ibulkst_cb_count); | ||
2080 | call->count = 0; | ||
2081 | call->unmarshall++; | ||
2082 | more_cbs: | ||
2083 | afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack)); | ||
2084 | |||
2085 | case 4: | ||
2086 | _debug("extract CB array"); | ||
2087 | ret = afs_extract_data(call, true); | ||
2088 | if (ret < 0) | ||
2089 | return ret; | ||
2090 | |||
2091 | _debug("unmarshall CB array"); | ||
2092 | bp = call->buffer; | ||
2093 | callbacks = call->reply[2]; | ||
2094 | xdr_decode_YFSCallBack_raw(&bp, &callbacks[call->count]); | ||
2095 | statuses = call->reply[1]; | ||
2096 | if (call->count == 0 && vnode && statuses[0].abort_code == 0) { | ||
2097 | bp = call->buffer; | ||
2098 | xdr_decode_YFSCallBack(call, vnode, &bp); | ||
2099 | } | ||
2100 | call->count++; | ||
2101 | if (call->count < call->count2) | ||
2102 | goto more_cbs; | ||
2103 | |||
2104 | afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync)); | ||
2105 | call->unmarshall++; | ||
2106 | |||
2107 | case 5: | ||
2108 | ret = afs_extract_data(call, false); | ||
2109 | if (ret < 0) | ||
2110 | return ret; | ||
2111 | |||
2112 | bp = call->buffer; | ||
2113 | xdr_decode_YFSVolSync(&bp, call->reply[3]); | ||
2114 | |||
2115 | call->unmarshall++; | ||
2116 | |||
2117 | case 6: | ||
2118 | break; | ||
2119 | } | ||
2120 | |||
2121 | _leave(" = 0 [done]"); | ||
2122 | return 0; | ||
2123 | } | ||
2124 | |||
2125 | /* | ||
2126 | * FS.InlineBulkStatus operation type | ||
2127 | */ | ||
2128 | static const struct afs_call_type yfs_RXYFSInlineBulkStatus = { | ||
2129 | .name = "YFS.InlineBulkStatus", | ||
2130 | .op = yfs_FS_InlineBulkStatus, | ||
2131 | .deliver = yfs_deliver_fs_inline_bulk_status, | ||
2132 | .destructor = afs_flat_call_destructor, | ||
2133 | }; | ||
2134 | |||
2135 | /* | ||
2136 | * Fetch the status information for up to 1024 files | ||
2137 | */ | ||
2138 | int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | ||
2139 | struct afs_net *net, | ||
2140 | struct afs_fid *fids, | ||
2141 | struct afs_file_status *statuses, | ||
2142 | struct afs_callback *callbacks, | ||
2143 | unsigned int nr_fids, | ||
2144 | struct afs_volsync *volsync) | ||
2145 | { | ||
2146 | struct afs_call *call; | ||
2147 | __be32 *bp; | ||
2148 | int i; | ||
2149 | |||
2150 | _enter(",%x,{%llx:%llu},%u", | ||
2151 | key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); | ||
2152 | |||
2153 | call = afs_alloc_flat_call(net, &yfs_RXYFSInlineBulkStatus, | ||
2154 | sizeof(__be32) + | ||
2155 | sizeof(__be32) + | ||
2156 | sizeof(__be32) + | ||
2157 | sizeof(struct yfs_xdr_YFSFid) * nr_fids, | ||
2158 | sizeof(struct yfs_xdr_YFSFetchStatus)); | ||
2159 | if (!call) { | ||
2160 | fc->ac.error = -ENOMEM; | ||
2161 | return -ENOMEM; | ||
2162 | } | ||
2163 | |||
2164 | call->key = fc->key; | ||
2165 | call->reply[0] = NULL; /* vnode for fid[0] */ | ||
2166 | call->reply[1] = statuses; | ||
2167 | call->reply[2] = callbacks; | ||
2168 | call->reply[3] = volsync; | ||
2169 | call->count2 = nr_fids; | ||
2170 | |||
2171 | /* marshall the parameters */ | ||
2172 | bp = call->request; | ||
2173 | bp = xdr_encode_u32(bp, YFSINLINEBULKSTATUS); | ||
2174 | bp = xdr_encode_u32(bp, 0); /* RPCFlags */ | ||
2175 | bp = xdr_encode_u32(bp, nr_fids); | ||
2176 | for (i = 0; i < nr_fids; i++) | ||
2177 | bp = xdr_encode_YFSFid(bp, &fids[i]); | ||
2178 | yfs_check_req(call, bp); | ||
2179 | |||
2180 | call->cb_break = fc->cb_break; | ||
2181 | afs_use_fs_server(call, fc->cbi); | ||
2182 | trace_afs_make_fs_call(call, &fids[0]); | ||
2183 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
2184 | } | ||
diff --git a/fs/block_dev.c b/fs/block_dev.c index 38b8ce05cbc7..a80b4f0ee7c4 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -349,7 +349,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) | |||
349 | 349 | ||
350 | dio->size = 0; | 350 | dio->size = 0; |
351 | dio->multi_bio = false; | 351 | dio->multi_bio = false; |
352 | dio->should_dirty = is_read && (iter->type == ITER_IOVEC); | 352 | dio->should_dirty = is_read && iter_is_iovec(iter); |
353 | 353 | ||
354 | blk_start_plug(&plug); | 354 | blk_start_plug(&plug); |
355 | for (;;) { | 355 | for (;;) { |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index f788496fafcc..27cad84dab23 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -615,7 +615,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to, | |||
615 | 615 | ||
616 | more = len < iov_iter_count(to); | 616 | more = len < iov_iter_count(to); |
617 | 617 | ||
618 | if (unlikely(to->type & ITER_PIPE)) { | 618 | if (unlikely(iov_iter_is_pipe(to))) { |
619 | ret = iov_iter_get_pages_alloc(to, &pages, len, | 619 | ret = iov_iter_get_pages_alloc(to, &pages, len, |
620 | &page_off); | 620 | &page_off); |
621 | if (ret <= 0) { | 621 | if (ret <= 0) { |
@@ -662,7 +662,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to, | |||
662 | ret += zlen; | 662 | ret += zlen; |
663 | } | 663 | } |
664 | 664 | ||
665 | if (unlikely(to->type & ITER_PIPE)) { | 665 | if (unlikely(iov_iter_is_pipe(to))) { |
666 | if (ret > 0) { | 666 | if (ret > 0) { |
667 | iov_iter_advance(to, ret); | 667 | iov_iter_advance(to, ret); |
668 | off += ret; | 668 | off += ret; |
@@ -815,7 +815,7 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req) | |||
815 | aio_req->total_len = rc + zlen; | 815 | aio_req->total_len = rc + zlen; |
816 | } | 816 | } |
817 | 817 | ||
818 | iov_iter_bvec(&i, ITER_BVEC, osd_data->bvec_pos.bvecs, | 818 | iov_iter_bvec(&i, READ, osd_data->bvec_pos.bvecs, |
819 | osd_data->num_bvecs, | 819 | osd_data->num_bvecs, |
820 | osd_data->bvec_pos.iter.bi_size); | 820 | osd_data->bvec_pos.iter.bi_size); |
821 | iov_iter_advance(&i, rc); | 821 | iov_iter_advance(&i, rc); |
@@ -1038,8 +1038,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter, | |||
1038 | int zlen = min_t(size_t, len - ret, | 1038 | int zlen = min_t(size_t, len - ret, |
1039 | size - pos - ret); | 1039 | size - pos - ret); |
1040 | 1040 | ||
1041 | iov_iter_bvec(&i, ITER_BVEC, bvecs, num_pages, | 1041 | iov_iter_bvec(&i, READ, bvecs, num_pages, len); |
1042 | len); | ||
1043 | iov_iter_advance(&i, ret); | 1042 | iov_iter_advance(&i, ret); |
1044 | iov_iter_zero(zlen, &i); | 1043 | iov_iter_zero(zlen, &i); |
1045 | ret += zlen; | 1044 | ret += zlen; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d82f0cc71755..6f24f129a751 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -589,7 +589,7 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, | |||
589 | { | 589 | { |
590 | struct msghdr smb_msg; | 590 | struct msghdr smb_msg; |
591 | struct kvec iov = {.iov_base = buf, .iov_len = to_read}; | 591 | struct kvec iov = {.iov_base = buf, .iov_len = to_read}; |
592 | iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read); | 592 | iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read); |
593 | 593 | ||
594 | return cifs_readv_from_socket(server, &smb_msg); | 594 | return cifs_readv_from_socket(server, &smb_msg); |
595 | } | 595 | } |
@@ -601,7 +601,7 @@ cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page, | |||
601 | struct msghdr smb_msg; | 601 | struct msghdr smb_msg; |
602 | struct bio_vec bv = { | 602 | struct bio_vec bv = { |
603 | .bv_page = page, .bv_len = to_read, .bv_offset = page_offset}; | 603 | .bv_page = page, .bv_len = to_read, .bv_offset = page_offset}; |
604 | iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read); | 604 | iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read); |
605 | return cifs_readv_from_socket(server, &smb_msg); | 605 | return cifs_readv_from_socket(server, &smb_msg); |
606 | } | 606 | } |
607 | 607 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c620d4b5d5d4..e262a05a98bf 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -3004,7 +3004,7 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter) | |||
3004 | size_t copy = min_t(size_t, remaining, PAGE_SIZE); | 3004 | size_t copy = min_t(size_t, remaining, PAGE_SIZE); |
3005 | size_t written; | 3005 | size_t written; |
3006 | 3006 | ||
3007 | if (unlikely(iter->type & ITER_PIPE)) { | 3007 | if (unlikely(iov_iter_is_pipe(iter))) { |
3008 | void *addr = kmap_atomic(page); | 3008 | void *addr = kmap_atomic(page); |
3009 | 3009 | ||
3010 | written = copy_to_iter(addr, copy, iter); | 3010 | written = copy_to_iter(addr, copy, iter); |
@@ -3316,7 +3316,7 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | |||
3316 | if (!is_sync_kiocb(iocb)) | 3316 | if (!is_sync_kiocb(iocb)) |
3317 | ctx->iocb = iocb; | 3317 | ctx->iocb = iocb; |
3318 | 3318 | ||
3319 | if (to->type == ITER_IOVEC) | 3319 | if (iter_is_iovec(to)) |
3320 | ctx->should_dirty = true; | 3320 | ctx->should_dirty = true; |
3321 | 3321 | ||
3322 | rc = setup_aio_ctx_iter(ctx, to, READ); | 3322 | rc = setup_aio_ctx_iter(ctx, to, READ); |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index fc43d5d25d1d..8a41f4eba726 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -788,7 +788,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) | |||
788 | struct page **pages = NULL; | 788 | struct page **pages = NULL; |
789 | struct bio_vec *bv = NULL; | 789 | struct bio_vec *bv = NULL; |
790 | 790 | ||
791 | if (iter->type & ITER_KVEC) { | 791 | if (iov_iter_is_kvec(iter)) { |
792 | memcpy(&ctx->iter, iter, sizeof(struct iov_iter)); | 792 | memcpy(&ctx->iter, iter, sizeof(struct iov_iter)); |
793 | ctx->len = count; | 793 | ctx->len = count; |
794 | iov_iter_advance(iter, count); | 794 | iov_iter_advance(iter, count); |
@@ -859,7 +859,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) | |||
859 | ctx->bv = bv; | 859 | ctx->bv = bv; |
860 | ctx->len = saved_len - count; | 860 | ctx->len = saved_len - count; |
861 | ctx->npages = npages; | 861 | ctx->npages = npages; |
862 | iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len); | 862 | iov_iter_bvec(&ctx->iter, rw, ctx->bv, npages, ctx->len); |
863 | return 0; | 863 | return 0; |
864 | } | 864 | } |
865 | 865 | ||
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f85fc5aa2710..23c0a21a66f8 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -3152,13 +3152,13 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, | |||
3152 | return 0; | 3152 | return 0; |
3153 | } | 3153 | } |
3154 | 3154 | ||
3155 | iov_iter_bvec(&iter, WRITE | ITER_BVEC, bvec, npages, data_len); | 3155 | iov_iter_bvec(&iter, WRITE, bvec, npages, data_len); |
3156 | } else if (buf_len >= data_offset + data_len) { | 3156 | } else if (buf_len >= data_offset + data_len) { |
3157 | /* read response payload is in buf */ | 3157 | /* read response payload is in buf */ |
3158 | WARN_ONCE(npages > 0, "read data can be either in buf or in pages"); | 3158 | WARN_ONCE(npages > 0, "read data can be either in buf or in pages"); |
3159 | iov.iov_base = buf + data_offset; | 3159 | iov.iov_base = buf + data_offset; |
3160 | iov.iov_len = data_len; | 3160 | iov.iov_len = data_len; |
3161 | iov_iter_kvec(&iter, WRITE | ITER_KVEC, &iov, 1, data_len); | 3161 | iov_iter_kvec(&iter, WRITE, &iov, 1, data_len); |
3162 | } else { | 3162 | } else { |
3163 | /* read response payload cannot be in both buf and pages */ | 3163 | /* read response payload cannot be in both buf and pages */ |
3164 | WARN_ONCE(1, "buf can not contain only a part of read data"); | 3164 | WARN_ONCE(1, "buf can not contain only a part of read data"); |
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index 5e282368cc4a..e94a8d1d08a3 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c | |||
@@ -2054,14 +2054,22 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) | |||
2054 | 2054 | ||
2055 | info->smbd_recv_pending++; | 2055 | info->smbd_recv_pending++; |
2056 | 2056 | ||
2057 | switch (msg->msg_iter.type) { | 2057 | if (iov_iter_rw(&msg->msg_iter) == WRITE) { |
2058 | case READ | ITER_KVEC: | 2058 | /* It's a bug in upper layer to get there */ |
2059 | cifs_dbg(VFS, "CIFS: invalid msg iter dir %u\n", | ||
2060 | iov_iter_rw(&msg->msg_iter)); | ||
2061 | rc = -EINVAL; | ||
2062 | goto out; | ||
2063 | } | ||
2064 | |||
2065 | switch (iov_iter_type(&msg->msg_iter)) { | ||
2066 | case ITER_KVEC: | ||
2059 | buf = msg->msg_iter.kvec->iov_base; | 2067 | buf = msg->msg_iter.kvec->iov_base; |
2060 | to_read = msg->msg_iter.kvec->iov_len; | 2068 | to_read = msg->msg_iter.kvec->iov_len; |
2061 | rc = smbd_recv_buf(info, buf, to_read); | 2069 | rc = smbd_recv_buf(info, buf, to_read); |
2062 | break; | 2070 | break; |
2063 | 2071 | ||
2064 | case READ | ITER_BVEC: | 2072 | case ITER_BVEC: |
2065 | page = msg->msg_iter.bvec->bv_page; | 2073 | page = msg->msg_iter.bvec->bv_page; |
2066 | page_offset = msg->msg_iter.bvec->bv_offset; | 2074 | page_offset = msg->msg_iter.bvec->bv_offset; |
2067 | to_read = msg->msg_iter.bvec->bv_len; | 2075 | to_read = msg->msg_iter.bvec->bv_len; |
@@ -2071,10 +2079,11 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) | |||
2071 | default: | 2079 | default: |
2072 | /* It's a bug in upper layer to get there */ | 2080 | /* It's a bug in upper layer to get there */ |
2073 | cifs_dbg(VFS, "CIFS: invalid msg type %d\n", | 2081 | cifs_dbg(VFS, "CIFS: invalid msg type %d\n", |
2074 | msg->msg_iter.type); | 2082 | iov_iter_type(&msg->msg_iter)); |
2075 | rc = -EINVAL; | 2083 | rc = -EINVAL; |
2076 | } | 2084 | } |
2077 | 2085 | ||
2086 | out: | ||
2078 | info->smbd_recv_pending--; | 2087 | info->smbd_recv_pending--; |
2079 | wake_up(&info->wait_smbd_recv_pending); | 2088 | wake_up(&info->wait_smbd_recv_pending); |
2080 | 2089 | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index f8112433f0c8..83ff0c25710d 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -316,8 +316,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, | |||
316 | .iov_base = &rfc1002_marker, | 316 | .iov_base = &rfc1002_marker, |
317 | .iov_len = 4 | 317 | .iov_len = 4 |
318 | }; | 318 | }; |
319 | iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, &hiov, | 319 | iov_iter_kvec(&smb_msg.msg_iter, WRITE, &hiov, 1, 4); |
320 | 1, 4); | ||
321 | rc = smb_send_kvec(server, &smb_msg, &sent); | 320 | rc = smb_send_kvec(server, &smb_msg, &sent); |
322 | if (rc < 0) | 321 | if (rc < 0) |
323 | goto uncork; | 322 | goto uncork; |
@@ -338,8 +337,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, | |||
338 | size += iov[i].iov_len; | 337 | size += iov[i].iov_len; |
339 | } | 338 | } |
340 | 339 | ||
341 | iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, | 340 | iov_iter_kvec(&smb_msg.msg_iter, WRITE, iov, n_vec, size); |
342 | iov, n_vec, size); | ||
343 | 341 | ||
344 | rc = smb_send_kvec(server, &smb_msg, &sent); | 342 | rc = smb_send_kvec(server, &smb_msg, &sent); |
345 | if (rc < 0) | 343 | if (rc < 0) |
@@ -355,7 +353,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, | |||
355 | rqst_page_get_length(&rqst[j], i, &bvec.bv_len, | 353 | rqst_page_get_length(&rqst[j], i, &bvec.bv_len, |
356 | &bvec.bv_offset); | 354 | &bvec.bv_offset); |
357 | 355 | ||
358 | iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC, | 356 | iov_iter_bvec(&smb_msg.msg_iter, WRITE, |
359 | &bvec, 1, bvec.bv_len); | 357 | &bvec, 1, bvec.bv_len); |
360 | rc = smb_send_kvec(server, &smb_msg, &sent); | 358 | rc = smb_send_kvec(server, &smb_msg, &sent); |
361 | if (rc < 0) | 359 | if (rc < 0) |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 093fb54cd316..722d17c88edb 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -1313,7 +1313,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, | |||
1313 | spin_lock_init(&dio->bio_lock); | 1313 | spin_lock_init(&dio->bio_lock); |
1314 | dio->refcount = 1; | 1314 | dio->refcount = 1; |
1315 | 1315 | ||
1316 | dio->should_dirty = (iter->type == ITER_IOVEC); | 1316 | dio->should_dirty = iter_is_iovec(iter) && iov_iter_rw(iter) == READ; |
1317 | sdio.iter = iter; | 1317 | sdio.iter = iter; |
1318 | sdio.final_block_in_request = end >> blkbits; | 1318 | sdio.final_block_in_request = end >> blkbits; |
1319 | 1319 | ||
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index a5e4a221435c..76976d6e50f9 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -674,7 +674,7 @@ static int receive_from_sock(struct connection *con) | |||
674 | nvec = 2; | 674 | nvec = 2; |
675 | } | 675 | } |
676 | len = iov[0].iov_len + iov[1].iov_len; | 676 | len = iov[0].iov_len + iov[1].iov_len; |
677 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, nvec, len); | 677 | iov_iter_kvec(&msg.msg_iter, READ, iov, nvec, len); |
678 | 678 | ||
679 | r = ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT | MSG_NOSIGNAL); | 679 | r = ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT | MSG_NOSIGNAL); |
680 | if (ret <= 0) | 680 | if (ret <= 0) |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 58dbc39fea63..cc2121b37bf5 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -1275,7 +1275,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii, | |||
1275 | ssize_t ret = 0; | 1275 | ssize_t ret = 0; |
1276 | 1276 | ||
1277 | /* Special case for kernel I/O: can copy directly into the buffer */ | 1277 | /* Special case for kernel I/O: can copy directly into the buffer */ |
1278 | if (ii->type & ITER_KVEC) { | 1278 | if (iov_iter_is_kvec(ii)) { |
1279 | unsigned long user_addr = fuse_get_user_addr(ii); | 1279 | unsigned long user_addr = fuse_get_user_addr(ii); |
1280 | size_t frag_size = fuse_get_frag_size(ii, *nbytesp); | 1280 | size_t frag_size = fuse_get_frag_size(ii, *nbytesp); |
1281 | 1281 | ||
diff --git a/fs/iomap.c b/fs/iomap.c index 90c2febc93ac..970ee3964e98 100644 --- a/fs/iomap.c +++ b/fs/iomap.c | |||
@@ -1795,7 +1795,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
1795 | if (pos >= dio->i_size) | 1795 | if (pos >= dio->i_size) |
1796 | goto out_free_dio; | 1796 | goto out_free_dio; |
1797 | 1797 | ||
1798 | if (iter->type == ITER_IOVEC) | 1798 | if (iter_is_iovec(iter) && iov_iter_rw(iter) == READ) |
1799 | dio->flags |= IOMAP_DIO_DIRTY; | 1799 | dio->flags |= IOMAP_DIO_DIRTY; |
1800 | } else { | 1800 | } else { |
1801 | flags |= IOMAP_WRITE; | 1801 | flags |= IOMAP_WRITE; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 2751976704e9..fb28be653014 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -923,7 +923,7 @@ __be32 nfsd_readv(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
923 | int host_err; | 923 | int host_err; |
924 | 924 | ||
925 | trace_nfsd_read_vector(rqstp, fhp, offset, *count); | 925 | trace_nfsd_read_vector(rqstp, fhp, offset, *count); |
926 | iov_iter_kvec(&iter, READ | ITER_KVEC, vec, vlen, *count); | 926 | iov_iter_kvec(&iter, READ, vec, vlen, *count); |
927 | host_err = vfs_iter_read(file, &iter, &offset, 0); | 927 | host_err = vfs_iter_read(file, &iter, &offset, 0); |
928 | return nfsd_finish_read(rqstp, fhp, file, offset, count, host_err); | 928 | return nfsd_finish_read(rqstp, fhp, file, offset, count, host_err); |
929 | } | 929 | } |
@@ -999,7 +999,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
999 | if (stable && !use_wgather) | 999 | if (stable && !use_wgather) |
1000 | flags |= RWF_SYNC; | 1000 | flags |= RWF_SYNC; |
1001 | 1001 | ||
1002 | iov_iter_kvec(&iter, WRITE | ITER_KVEC, vec, vlen, *cnt); | 1002 | iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt); |
1003 | host_err = vfs_iter_write(file, &iter, &pos, flags); | 1003 | host_err = vfs_iter_write(file, &iter, &pos, flags); |
1004 | if (host_err < 0) | 1004 | if (host_err < 0) |
1005 | goto out_nfserr; | 1005 | goto out_nfserr; |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 7d9eea7d4a87..e9f236af1927 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -916,7 +916,7 @@ static int o2net_recv_tcp_msg(struct socket *sock, void *data, size_t len) | |||
916 | { | 916 | { |
917 | struct kvec vec = { .iov_len = len, .iov_base = data, }; | 917 | struct kvec vec = { .iov_len = len, .iov_base = data, }; |
918 | struct msghdr msg = { .msg_flags = MSG_DONTWAIT, }; | 918 | struct msghdr msg = { .msg_flags = MSG_DONTWAIT, }; |
919 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &vec, 1, len); | 919 | iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, len); |
920 | return sock_recvmsg(sock, &msg, MSG_DONTWAIT); | 920 | return sock_recvmsg(sock, &msg, MSG_DONTWAIT); |
921 | } | 921 | } |
922 | 922 | ||
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index 5e65d818937b..fe53381b26b1 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c | |||
@@ -25,7 +25,7 @@ static int read_one_page(struct page *page) | |||
25 | struct iov_iter to; | 25 | struct iov_iter to; |
26 | struct bio_vec bv = {.bv_page = page, .bv_len = PAGE_SIZE}; | 26 | struct bio_vec bv = {.bv_page = page, .bv_len = PAGE_SIZE}; |
27 | 27 | ||
28 | iov_iter_bvec(&to, ITER_BVEC | READ, &bv, 1, PAGE_SIZE); | 28 | iov_iter_bvec(&to, READ, &bv, 1, PAGE_SIZE); |
29 | 29 | ||
30 | gossip_debug(GOSSIP_INODE_DEBUG, | 30 | gossip_debug(GOSSIP_INODE_DEBUG, |
31 | "orangefs_readpage called with page %p\n", | 31 | "orangefs_readpage called with page %p\n", |
diff --git a/fs/splice.c b/fs/splice.c index b3daa971f597..3553f1956508 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -301,7 +301,7 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
301 | struct kiocb kiocb; | 301 | struct kiocb kiocb; |
302 | int idx, ret; | 302 | int idx, ret; |
303 | 303 | ||
304 | iov_iter_pipe(&to, ITER_PIPE | READ, pipe, len); | 304 | iov_iter_pipe(&to, READ, pipe, len); |
305 | idx = to.idx; | 305 | idx = to.idx; |
306 | init_sync_kiocb(&kiocb, in); | 306 | init_sync_kiocb(&kiocb, in); |
307 | kiocb.ki_pos = *ppos; | 307 | kiocb.ki_pos = *ppos; |
@@ -386,7 +386,7 @@ static ssize_t default_file_splice_read(struct file *in, loff_t *ppos, | |||
386 | */ | 386 | */ |
387 | offset = *ppos & ~PAGE_MASK; | 387 | offset = *ppos & ~PAGE_MASK; |
388 | 388 | ||
389 | iov_iter_pipe(&to, ITER_PIPE | READ, pipe, len + offset); | 389 | iov_iter_pipe(&to, READ, pipe, len + offset); |
390 | 390 | ||
391 | res = iov_iter_get_pages_alloc(&to, &pages, len + offset, &base); | 391 | res = iov_iter_get_pages_alloc(&to, &pages, len + offset, &base); |
392 | if (res <= 0) | 392 | if (res <= 0) |
@@ -745,8 +745,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
745 | left -= this_len; | 745 | left -= this_len; |
746 | } | 746 | } |
747 | 747 | ||
748 | iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n, | 748 | iov_iter_bvec(&from, WRITE, array, n, sd.total_len - left); |
749 | sd.total_len - left); | ||
750 | ret = vfs_iter_write(out, &from, &sd.pos, 0); | 749 | ret = vfs_iter_write(out, &from, &sd.pos, 0); |
751 | if (ret <= 0) | 750 | if (ret <= 0) |
752 | break; | 751 | break; |
diff --git a/include/linux/uio.h b/include/linux/uio.h index 422b1c01ee0d..55ce99ddb912 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
@@ -21,15 +21,16 @@ struct kvec { | |||
21 | size_t iov_len; | 21 | size_t iov_len; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | enum { | 24 | enum iter_type { |
25 | ITER_IOVEC = 0, | 25 | ITER_IOVEC = 0, |
26 | ITER_KVEC = 2, | 26 | ITER_KVEC = 2, |
27 | ITER_BVEC = 4, | 27 | ITER_BVEC = 4, |
28 | ITER_PIPE = 8, | 28 | ITER_PIPE = 8, |
29 | ITER_DISCARD = 16, | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | struct iov_iter { | 32 | struct iov_iter { |
32 | int type; | 33 | unsigned int type; |
33 | size_t iov_offset; | 34 | size_t iov_offset; |
34 | size_t count; | 35 | size_t count; |
35 | union { | 36 | union { |
@@ -47,6 +48,41 @@ struct iov_iter { | |||
47 | }; | 48 | }; |
48 | }; | 49 | }; |
49 | 50 | ||
51 | static inline enum iter_type iov_iter_type(const struct iov_iter *i) | ||
52 | { | ||
53 | return i->type & ~(READ | WRITE); | ||
54 | } | ||
55 | |||
56 | static inline bool iter_is_iovec(const struct iov_iter *i) | ||
57 | { | ||
58 | return iov_iter_type(i) == ITER_IOVEC; | ||
59 | } | ||
60 | |||
61 | static inline bool iov_iter_is_kvec(const struct iov_iter *i) | ||
62 | { | ||
63 | return iov_iter_type(i) == ITER_KVEC; | ||
64 | } | ||
65 | |||
66 | static inline bool iov_iter_is_bvec(const struct iov_iter *i) | ||
67 | { | ||
68 | return iov_iter_type(i) == ITER_BVEC; | ||
69 | } | ||
70 | |||
71 | static inline bool iov_iter_is_pipe(const struct iov_iter *i) | ||
72 | { | ||
73 | return iov_iter_type(i) == ITER_PIPE; | ||
74 | } | ||
75 | |||
76 | static inline bool iov_iter_is_discard(const struct iov_iter *i) | ||
77 | { | ||
78 | return iov_iter_type(i) == ITER_DISCARD; | ||
79 | } | ||
80 | |||
81 | static inline unsigned char iov_iter_rw(const struct iov_iter *i) | ||
82 | { | ||
83 | return i->type & (READ | WRITE); | ||
84 | } | ||
85 | |||
50 | /* | 86 | /* |
51 | * Total number of bytes covered by an iovec. | 87 | * Total number of bytes covered by an iovec. |
52 | * | 88 | * |
@@ -74,7 +110,8 @@ static inline struct iovec iov_iter_iovec(const struct iov_iter *iter) | |||
74 | } | 110 | } |
75 | 111 | ||
76 | #define iov_for_each(iov, iter, start) \ | 112 | #define iov_for_each(iov, iter, start) \ |
77 | if (!((start).type & (ITER_BVEC | ITER_PIPE))) \ | 113 | if (iov_iter_type(start) == ITER_IOVEC || \ |
114 | iov_iter_type(start) == ITER_KVEC) \ | ||
78 | for (iter = (start); \ | 115 | for (iter = (start); \ |
79 | (iter).count && \ | 116 | (iter).count && \ |
80 | ((iov = iov_iter_iovec(&(iter))), 1); \ | 117 | ((iov = iov_iter_iovec(&(iter))), 1); \ |
@@ -181,14 +218,15 @@ size_t copy_to_iter_mcsafe(void *addr, size_t bytes, struct iov_iter *i) | |||
181 | size_t iov_iter_zero(size_t bytes, struct iov_iter *); | 218 | size_t iov_iter_zero(size_t bytes, struct iov_iter *); |
182 | unsigned long iov_iter_alignment(const struct iov_iter *i); | 219 | unsigned long iov_iter_alignment(const struct iov_iter *i); |
183 | unsigned long iov_iter_gap_alignment(const struct iov_iter *i); | 220 | unsigned long iov_iter_gap_alignment(const struct iov_iter *i); |
184 | void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, | 221 | void iov_iter_init(struct iov_iter *i, unsigned int direction, const struct iovec *iov, |
185 | unsigned long nr_segs, size_t count); | 222 | unsigned long nr_segs, size_t count); |
186 | void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *kvec, | 223 | void iov_iter_kvec(struct iov_iter *i, unsigned int direction, const struct kvec *kvec, |
187 | unsigned long nr_segs, size_t count); | 224 | unsigned long nr_segs, size_t count); |
188 | void iov_iter_bvec(struct iov_iter *i, int direction, const struct bio_vec *bvec, | 225 | void iov_iter_bvec(struct iov_iter *i, unsigned int direction, const struct bio_vec *bvec, |
189 | unsigned long nr_segs, size_t count); | 226 | unsigned long nr_segs, size_t count); |
190 | void iov_iter_pipe(struct iov_iter *i, int direction, struct pipe_inode_info *pipe, | 227 | void iov_iter_pipe(struct iov_iter *i, unsigned int direction, struct pipe_inode_info *pipe, |
191 | size_t count); | 228 | size_t count); |
229 | void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count); | ||
192 | ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, | 230 | ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, |
193 | size_t maxsize, unsigned maxpages, size_t *start); | 231 | size_t maxsize, unsigned maxpages, size_t *start); |
194 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, | 232 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, |
@@ -202,19 +240,6 @@ static inline size_t iov_iter_count(const struct iov_iter *i) | |||
202 | return i->count; | 240 | return i->count; |
203 | } | 241 | } |
204 | 242 | ||
205 | static inline bool iter_is_iovec(const struct iov_iter *i) | ||
206 | { | ||
207 | return !(i->type & (ITER_BVEC | ITER_KVEC | ITER_PIPE)); | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * Get one of READ or WRITE out of iter->type without any other flags OR'd in | ||
212 | * with it. | ||
213 | * | ||
214 | * The ?: is just for type safety. | ||
215 | */ | ||
216 | #define iov_iter_rw(i) ((0 ? (struct iov_iter *)0 : (i))->type & (READ | WRITE)) | ||
217 | |||
218 | /* | 243 | /* |
219 | * Cap the iov_iter by given limit; note that the second argument is | 244 | * Cap the iov_iter by given limit; note that the second argument is |
220 | * *not* the new size - it's upper limit for such. Passing it a value | 245 | * *not* the new size - it's upper limit for such. Passing it a value |
diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index d0a341bc4540..33d291888ba9 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h | |||
@@ -54,6 +54,35 @@ enum afs_fs_operation { | |||
54 | afs_FS_StoreData64 = 65538, /* AFS Store file data */ | 54 | afs_FS_StoreData64 = 65538, /* AFS Store file data */ |
55 | afs_FS_GiveUpAllCallBacks = 65539, /* AFS Give up all our callbacks on a server */ | 55 | afs_FS_GiveUpAllCallBacks = 65539, /* AFS Give up all our callbacks on a server */ |
56 | afs_FS_GetCapabilities = 65540, /* AFS Get FS server capabilities */ | 56 | afs_FS_GetCapabilities = 65540, /* AFS Get FS server capabilities */ |
57 | |||
58 | yfs_FS_FetchData = 130, /* YFS Fetch file data */ | ||
59 | yfs_FS_FetchACL = 64131, /* YFS Fetch file ACL */ | ||
60 | yfs_FS_FetchStatus = 64132, /* YFS Fetch file status */ | ||
61 | yfs_FS_StoreACL = 64134, /* YFS Store file ACL */ | ||
62 | yfs_FS_StoreStatus = 64135, /* YFS Store file status */ | ||
63 | yfs_FS_RemoveFile = 64136, /* YFS Remove a file */ | ||
64 | yfs_FS_CreateFile = 64137, /* YFS Create a file */ | ||
65 | yfs_FS_Rename = 64138, /* YFS Rename or move a file or directory */ | ||
66 | yfs_FS_Symlink = 64139, /* YFS Create a symbolic link */ | ||
67 | yfs_FS_Link = 64140, /* YFS Create a hard link */ | ||
68 | yfs_FS_MakeDir = 64141, /* YFS Create a directory */ | ||
69 | yfs_FS_RemoveDir = 64142, /* YFS Remove a directory */ | ||
70 | yfs_FS_GetVolumeStatus = 64149, /* YFS Get volume status information */ | ||
71 | yfs_FS_SetVolumeStatus = 64150, /* YFS Set volume status information */ | ||
72 | yfs_FS_SetLock = 64156, /* YFS Request a file lock */ | ||
73 | yfs_FS_ExtendLock = 64157, /* YFS Extend a file lock */ | ||
74 | yfs_FS_ReleaseLock = 64158, /* YFS Release a file lock */ | ||
75 | yfs_FS_Lookup = 64161, /* YFS lookup file in directory */ | ||
76 | yfs_FS_FlushCPS = 64165, | ||
77 | yfs_FS_FetchOpaqueACL = 64168, | ||
78 | yfs_FS_WhoAmI = 64170, | ||
79 | yfs_FS_RemoveACL = 64171, | ||
80 | yfs_FS_RemoveFile2 = 64173, | ||
81 | yfs_FS_StoreOpaqueACL2 = 64174, | ||
82 | yfs_FS_InlineBulkStatus = 64536, /* YFS Fetch multiple file statuses with errors */ | ||
83 | yfs_FS_FetchData64 = 64537, /* YFS Fetch file data */ | ||
84 | yfs_FS_StoreData64 = 64538, /* YFS Store file data */ | ||
85 | yfs_FS_UpdateSymlink = 64540, | ||
57 | }; | 86 | }; |
58 | 87 | ||
59 | enum afs_vl_operation { | 88 | enum afs_vl_operation { |
@@ -84,6 +113,44 @@ enum afs_edit_dir_reason { | |||
84 | afs_edit_dir_for_unlink, | 113 | afs_edit_dir_for_unlink, |
85 | }; | 114 | }; |
86 | 115 | ||
116 | enum afs_eproto_cause { | ||
117 | afs_eproto_bad_status, | ||
118 | afs_eproto_cb_count, | ||
119 | afs_eproto_cb_fid_count, | ||
120 | afs_eproto_file_type, | ||
121 | afs_eproto_ibulkst_cb_count, | ||
122 | afs_eproto_ibulkst_count, | ||
123 | afs_eproto_motd_len, | ||
124 | afs_eproto_offline_msg_len, | ||
125 | afs_eproto_volname_len, | ||
126 | afs_eproto_yvl_fsendpt4_len, | ||
127 | afs_eproto_yvl_fsendpt6_len, | ||
128 | afs_eproto_yvl_fsendpt_num, | ||
129 | afs_eproto_yvl_fsendpt_type, | ||
130 | afs_eproto_yvl_vlendpt4_len, | ||
131 | afs_eproto_yvl_vlendpt6_len, | ||
132 | afs_eproto_yvl_vlendpt_type, | ||
133 | }; | ||
134 | |||
135 | enum afs_io_error { | ||
136 | afs_io_error_cm_reply, | ||
137 | afs_io_error_extract, | ||
138 | afs_io_error_fs_probe_fail, | ||
139 | afs_io_error_vl_lookup_fail, | ||
140 | afs_io_error_vl_probe_fail, | ||
141 | }; | ||
142 | |||
143 | enum afs_file_error { | ||
144 | afs_file_error_dir_bad_magic, | ||
145 | afs_file_error_dir_big, | ||
146 | afs_file_error_dir_missing_page, | ||
147 | afs_file_error_dir_over_end, | ||
148 | afs_file_error_dir_small, | ||
149 | afs_file_error_dir_unmarked_ext, | ||
150 | afs_file_error_mntpt, | ||
151 | afs_file_error_writeback_fail, | ||
152 | }; | ||
153 | |||
87 | #endif /* end __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY */ | 154 | #endif /* end __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY */ |
88 | 155 | ||
89 | /* | 156 | /* |
@@ -119,7 +186,34 @@ enum afs_edit_dir_reason { | |||
119 | EM(afs_FS_FetchData64, "FS.FetchData64") \ | 186 | EM(afs_FS_FetchData64, "FS.FetchData64") \ |
120 | EM(afs_FS_StoreData64, "FS.StoreData64") \ | 187 | EM(afs_FS_StoreData64, "FS.StoreData64") \ |
121 | EM(afs_FS_GiveUpAllCallBacks, "FS.GiveUpAllCallBacks") \ | 188 | EM(afs_FS_GiveUpAllCallBacks, "FS.GiveUpAllCallBacks") \ |
122 | E_(afs_FS_GetCapabilities, "FS.GetCapabilities") | 189 | EM(afs_FS_GetCapabilities, "FS.GetCapabilities") \ |
190 | EM(yfs_FS_FetchACL, "YFS.FetchACL") \ | ||
191 | EM(yfs_FS_FetchStatus, "YFS.FetchStatus") \ | ||
192 | EM(yfs_FS_StoreACL, "YFS.StoreACL") \ | ||
193 | EM(yfs_FS_StoreStatus, "YFS.StoreStatus") \ | ||
194 | EM(yfs_FS_RemoveFile, "YFS.RemoveFile") \ | ||
195 | EM(yfs_FS_CreateFile, "YFS.CreateFile") \ | ||
196 | EM(yfs_FS_Rename, "YFS.Rename") \ | ||
197 | EM(yfs_FS_Symlink, "YFS.Symlink") \ | ||
198 | EM(yfs_FS_Link, "YFS.Link") \ | ||
199 | EM(yfs_FS_MakeDir, "YFS.MakeDir") \ | ||
200 | EM(yfs_FS_RemoveDir, "YFS.RemoveDir") \ | ||
201 | EM(yfs_FS_GetVolumeStatus, "YFS.GetVolumeStatus") \ | ||
202 | EM(yfs_FS_SetVolumeStatus, "YFS.SetVolumeStatus") \ | ||
203 | EM(yfs_FS_SetLock, "YFS.SetLock") \ | ||
204 | EM(yfs_FS_ExtendLock, "YFS.ExtendLock") \ | ||
205 | EM(yfs_FS_ReleaseLock, "YFS.ReleaseLock") \ | ||
206 | EM(yfs_FS_Lookup, "YFS.Lookup") \ | ||
207 | EM(yfs_FS_FlushCPS, "YFS.FlushCPS") \ | ||
208 | EM(yfs_FS_FetchOpaqueACL, "YFS.FetchOpaqueACL") \ | ||
209 | EM(yfs_FS_WhoAmI, "YFS.WhoAmI") \ | ||
210 | EM(yfs_FS_RemoveACL, "YFS.RemoveACL") \ | ||
211 | EM(yfs_FS_RemoveFile2, "YFS.RemoveFile2") \ | ||
212 | EM(yfs_FS_StoreOpaqueACL2, "YFS.StoreOpaqueACL2") \ | ||
213 | EM(yfs_FS_InlineBulkStatus, "YFS.InlineBulkStatus") \ | ||
214 | EM(yfs_FS_FetchData64, "YFS.FetchData64") \ | ||
215 | EM(yfs_FS_StoreData64, "YFS.StoreData64") \ | ||
216 | E_(yfs_FS_UpdateSymlink, "YFS.UpdateSymlink") | ||
123 | 217 | ||
124 | #define afs_vl_operations \ | 218 | #define afs_vl_operations \ |
125 | EM(afs_VL_GetEntryByNameU, "VL.GetEntryByNameU") \ | 219 | EM(afs_VL_GetEntryByNameU, "VL.GetEntryByNameU") \ |
@@ -146,6 +240,40 @@ enum afs_edit_dir_reason { | |||
146 | EM(afs_edit_dir_for_symlink, "Symlnk") \ | 240 | EM(afs_edit_dir_for_symlink, "Symlnk") \ |
147 | E_(afs_edit_dir_for_unlink, "Unlink") | 241 | E_(afs_edit_dir_for_unlink, "Unlink") |
148 | 242 | ||
243 | #define afs_eproto_causes \ | ||
244 | EM(afs_eproto_bad_status, "BadStatus") \ | ||
245 | EM(afs_eproto_cb_count, "CbCount") \ | ||
246 | EM(afs_eproto_cb_fid_count, "CbFidCount") \ | ||
247 | EM(afs_eproto_file_type, "FileTYpe") \ | ||
248 | EM(afs_eproto_ibulkst_cb_count, "IBS.CbCount") \ | ||
249 | EM(afs_eproto_ibulkst_count, "IBS.FidCount") \ | ||
250 | EM(afs_eproto_motd_len, "MotdLen") \ | ||
251 | EM(afs_eproto_offline_msg_len, "OfflineMsgLen") \ | ||
252 | EM(afs_eproto_volname_len, "VolNameLen") \ | ||
253 | EM(afs_eproto_yvl_fsendpt4_len, "YVL.FsEnd4Len") \ | ||
254 | EM(afs_eproto_yvl_fsendpt6_len, "YVL.FsEnd6Len") \ | ||
255 | EM(afs_eproto_yvl_fsendpt_num, "YVL.FsEndCount") \ | ||
256 | EM(afs_eproto_yvl_fsendpt_type, "YVL.FsEndType") \ | ||
257 | EM(afs_eproto_yvl_vlendpt4_len, "YVL.VlEnd4Len") \ | ||
258 | EM(afs_eproto_yvl_vlendpt6_len, "YVL.VlEnd6Len") \ | ||
259 | E_(afs_eproto_yvl_vlendpt_type, "YVL.VlEndType") | ||
260 | |||
261 | #define afs_io_errors \ | ||
262 | EM(afs_io_error_cm_reply, "CM_REPLY") \ | ||
263 | EM(afs_io_error_extract, "EXTRACT") \ | ||
264 | EM(afs_io_error_fs_probe_fail, "FS_PROBE_FAIL") \ | ||
265 | EM(afs_io_error_vl_lookup_fail, "VL_LOOKUP_FAIL") \ | ||
266 | E_(afs_io_error_vl_probe_fail, "VL_PROBE_FAIL") | ||
267 | |||
268 | #define afs_file_errors \ | ||
269 | EM(afs_file_error_dir_bad_magic, "DIR_BAD_MAGIC") \ | ||
270 | EM(afs_file_error_dir_big, "DIR_BIG") \ | ||
271 | EM(afs_file_error_dir_missing_page, "DIR_MISSING_PAGE") \ | ||
272 | EM(afs_file_error_dir_over_end, "DIR_ENT_OVER_END") \ | ||
273 | EM(afs_file_error_dir_small, "DIR_SMALL") \ | ||
274 | EM(afs_file_error_dir_unmarked_ext, "DIR_UNMARKED_EXT") \ | ||
275 | EM(afs_file_error_mntpt, "MNTPT_READ_FAILED") \ | ||
276 | E_(afs_file_error_writeback_fail, "WRITEBACK_FAILED") | ||
149 | 277 | ||
150 | /* | 278 | /* |
151 | * Export enum symbols via userspace. | 279 | * Export enum symbols via userspace. |
@@ -160,6 +288,9 @@ afs_fs_operations; | |||
160 | afs_vl_operations; | 288 | afs_vl_operations; |
161 | afs_edit_dir_ops; | 289 | afs_edit_dir_ops; |
162 | afs_edit_dir_reasons; | 290 | afs_edit_dir_reasons; |
291 | afs_eproto_causes; | ||
292 | afs_io_errors; | ||
293 | afs_file_errors; | ||
163 | 294 | ||
164 | /* | 295 | /* |
165 | * Now redefine the EM() and E_() macros to map the enums to the strings that | 296 | * Now redefine the EM() and E_() macros to map the enums to the strings that |
@@ -170,17 +301,16 @@ afs_edit_dir_reasons; | |||
170 | #define EM(a, b) { a, b }, | 301 | #define EM(a, b) { a, b }, |
171 | #define E_(a, b) { a, b } | 302 | #define E_(a, b) { a, b } |
172 | 303 | ||
173 | TRACE_EVENT(afs_recv_data, | 304 | TRACE_EVENT(afs_receive_data, |
174 | TP_PROTO(struct afs_call *call, unsigned count, unsigned offset, | 305 | TP_PROTO(struct afs_call *call, struct iov_iter *iter, |
175 | bool want_more, int ret), | 306 | bool want_more, int ret), |
176 | 307 | ||
177 | TP_ARGS(call, count, offset, want_more, ret), | 308 | TP_ARGS(call, iter, want_more, ret), |
178 | 309 | ||
179 | TP_STRUCT__entry( | 310 | TP_STRUCT__entry( |
311 | __field(loff_t, remain ) | ||
180 | __field(unsigned int, call ) | 312 | __field(unsigned int, call ) |
181 | __field(enum afs_call_state, state ) | 313 | __field(enum afs_call_state, state ) |
182 | __field(unsigned int, count ) | ||
183 | __field(unsigned int, offset ) | ||
184 | __field(unsigned short, unmarshall ) | 314 | __field(unsigned short, unmarshall ) |
185 | __field(bool, want_more ) | 315 | __field(bool, want_more ) |
186 | __field(int, ret ) | 316 | __field(int, ret ) |
@@ -190,17 +320,18 @@ TRACE_EVENT(afs_recv_data, | |||
190 | __entry->call = call->debug_id; | 320 | __entry->call = call->debug_id; |
191 | __entry->state = call->state; | 321 | __entry->state = call->state; |
192 | __entry->unmarshall = call->unmarshall; | 322 | __entry->unmarshall = call->unmarshall; |
193 | __entry->count = count; | 323 | __entry->remain = iov_iter_count(iter); |
194 | __entry->offset = offset; | ||
195 | __entry->want_more = want_more; | 324 | __entry->want_more = want_more; |
196 | __entry->ret = ret; | 325 | __entry->ret = ret; |
197 | ), | 326 | ), |
198 | 327 | ||
199 | TP_printk("c=%08x s=%u u=%u %u/%u wm=%u ret=%d", | 328 | TP_printk("c=%08x r=%llu u=%u w=%u s=%u ret=%d", |
200 | __entry->call, | 329 | __entry->call, |
201 | __entry->state, __entry->unmarshall, | 330 | __entry->remain, |
202 | __entry->offset, __entry->count, | 331 | __entry->unmarshall, |
203 | __entry->want_more, __entry->ret) | 332 | __entry->want_more, |
333 | __entry->state, | ||
334 | __entry->ret) | ||
204 | ); | 335 | ); |
205 | 336 | ||
206 | TRACE_EVENT(afs_notify_call, | 337 | TRACE_EVENT(afs_notify_call, |
@@ -301,7 +432,7 @@ TRACE_EVENT(afs_make_fs_call, | |||
301 | } | 432 | } |
302 | ), | 433 | ), |
303 | 434 | ||
304 | TP_printk("c=%08x %06x:%06x:%06x %s", | 435 | TP_printk("c=%08x %06llx:%06llx:%06x %s", |
305 | __entry->call, | 436 | __entry->call, |
306 | __entry->fid.vid, | 437 | __entry->fid.vid, |
307 | __entry->fid.vnode, | 438 | __entry->fid.vnode, |
@@ -555,24 +686,70 @@ TRACE_EVENT(afs_edit_dir, | |||
555 | ); | 686 | ); |
556 | 687 | ||
557 | TRACE_EVENT(afs_protocol_error, | 688 | TRACE_EVENT(afs_protocol_error, |
558 | TP_PROTO(struct afs_call *call, int error, const void *where), | 689 | TP_PROTO(struct afs_call *call, int error, enum afs_eproto_cause cause), |
690 | |||
691 | TP_ARGS(call, error, cause), | ||
692 | |||
693 | TP_STRUCT__entry( | ||
694 | __field(unsigned int, call ) | ||
695 | __field(int, error ) | ||
696 | __field(enum afs_eproto_cause, cause ) | ||
697 | ), | ||
698 | |||
699 | TP_fast_assign( | ||
700 | __entry->call = call ? call->debug_id : 0; | ||
701 | __entry->error = error; | ||
702 | __entry->cause = cause; | ||
703 | ), | ||
704 | |||
705 | TP_printk("c=%08x r=%d %s", | ||
706 | __entry->call, __entry->error, | ||
707 | __print_symbolic(__entry->cause, afs_eproto_causes)) | ||
708 | ); | ||
709 | |||
710 | TRACE_EVENT(afs_io_error, | ||
711 | TP_PROTO(unsigned int call, int error, enum afs_io_error where), | ||
559 | 712 | ||
560 | TP_ARGS(call, error, where), | 713 | TP_ARGS(call, error, where), |
561 | 714 | ||
562 | TP_STRUCT__entry( | 715 | TP_STRUCT__entry( |
563 | __field(unsigned int, call ) | 716 | __field(unsigned int, call ) |
564 | __field(int, error ) | 717 | __field(int, error ) |
565 | __field(const void *, where ) | 718 | __field(enum afs_io_error, where ) |
566 | ), | 719 | ), |
567 | 720 | ||
568 | TP_fast_assign( | 721 | TP_fast_assign( |
569 | __entry->call = call ? call->debug_id : 0; | 722 | __entry->call = call; |
723 | __entry->error = error; | ||
724 | __entry->where = where; | ||
725 | ), | ||
726 | |||
727 | TP_printk("c=%08x r=%d %s", | ||
728 | __entry->call, __entry->error, | ||
729 | __print_symbolic(__entry->where, afs_io_errors)) | ||
730 | ); | ||
731 | |||
732 | TRACE_EVENT(afs_file_error, | ||
733 | TP_PROTO(struct afs_vnode *vnode, int error, enum afs_file_error where), | ||
734 | |||
735 | TP_ARGS(vnode, error, where), | ||
736 | |||
737 | TP_STRUCT__entry( | ||
738 | __field_struct(struct afs_fid, fid ) | ||
739 | __field(int, error ) | ||
740 | __field(enum afs_file_error, where ) | ||
741 | ), | ||
742 | |||
743 | TP_fast_assign( | ||
744 | __entry->fid = vnode->fid; | ||
570 | __entry->error = error; | 745 | __entry->error = error; |
571 | __entry->where = where; | 746 | __entry->where = where; |
572 | ), | 747 | ), |
573 | 748 | ||
574 | TP_printk("c=%08x r=%d sp=%pSR", | 749 | TP_printk("%llx:%llx:%x r=%d %s", |
575 | __entry->call, __entry->error, __entry->where) | 750 | __entry->fid.vid, __entry->fid.vnode, __entry->fid.unique, |
751 | __entry->error, | ||
752 | __print_symbolic(__entry->where, afs_file_errors)) | ||
576 | ); | 753 | ); |
577 | 754 | ||
578 | TRACE_EVENT(afs_cm_no_server, | 755 | TRACE_EVENT(afs_cm_no_server, |
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 8be175df3075..7ebccb5c1637 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c | |||
@@ -83,6 +83,7 @@ | |||
83 | const struct kvec *kvec; \ | 83 | const struct kvec *kvec; \ |
84 | struct kvec v; \ | 84 | struct kvec v; \ |
85 | iterate_kvec(i, n, v, kvec, skip, (K)) \ | 85 | iterate_kvec(i, n, v, kvec, skip, (K)) \ |
86 | } else if (unlikely(i->type & ITER_DISCARD)) { \ | ||
86 | } else { \ | 87 | } else { \ |
87 | const struct iovec *iov; \ | 88 | const struct iovec *iov; \ |
88 | struct iovec v; \ | 89 | struct iovec v; \ |
@@ -114,6 +115,8 @@ | |||
114 | } \ | 115 | } \ |
115 | i->nr_segs -= kvec - i->kvec; \ | 116 | i->nr_segs -= kvec - i->kvec; \ |
116 | i->kvec = kvec; \ | 117 | i->kvec = kvec; \ |
118 | } else if (unlikely(i->type & ITER_DISCARD)) { \ | ||
119 | skip += n; \ | ||
117 | } else { \ | 120 | } else { \ |
118 | const struct iovec *iov; \ | 121 | const struct iovec *iov; \ |
119 | struct iovec v; \ | 122 | struct iovec v; \ |
@@ -428,17 +431,19 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) | |||
428 | } | 431 | } |
429 | EXPORT_SYMBOL(iov_iter_fault_in_readable); | 432 | EXPORT_SYMBOL(iov_iter_fault_in_readable); |
430 | 433 | ||
431 | void iov_iter_init(struct iov_iter *i, int direction, | 434 | void iov_iter_init(struct iov_iter *i, unsigned int direction, |
432 | const struct iovec *iov, unsigned long nr_segs, | 435 | const struct iovec *iov, unsigned long nr_segs, |
433 | size_t count) | 436 | size_t count) |
434 | { | 437 | { |
438 | WARN_ON(direction & ~(READ | WRITE)); | ||
439 | direction &= READ | WRITE; | ||
440 | |||
435 | /* It will get better. Eventually... */ | 441 | /* It will get better. Eventually... */ |
436 | if (uaccess_kernel()) { | 442 | if (uaccess_kernel()) { |
437 | direction |= ITER_KVEC; | 443 | i->type = ITER_KVEC | direction; |
438 | i->type = direction; | ||
439 | i->kvec = (struct kvec *)iov; | 444 | i->kvec = (struct kvec *)iov; |
440 | } else { | 445 | } else { |
441 | i->type = direction; | 446 | i->type = ITER_IOVEC | direction; |
442 | i->iov = iov; | 447 | i->iov = iov; |
443 | } | 448 | } |
444 | i->nr_segs = nr_segs; | 449 | i->nr_segs = nr_segs; |
@@ -558,7 +563,7 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes, | |||
558 | size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) | 563 | size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) |
559 | { | 564 | { |
560 | const char *from = addr; | 565 | const char *from = addr; |
561 | if (unlikely(i->type & ITER_PIPE)) | 566 | if (unlikely(iov_iter_is_pipe(i))) |
562 | return copy_pipe_to_iter(addr, bytes, i); | 567 | return copy_pipe_to_iter(addr, bytes, i); |
563 | if (iter_is_iovec(i)) | 568 | if (iter_is_iovec(i)) |
564 | might_fault(); | 569 | might_fault(); |
@@ -658,7 +663,7 @@ size_t _copy_to_iter_mcsafe(const void *addr, size_t bytes, struct iov_iter *i) | |||
658 | const char *from = addr; | 663 | const char *from = addr; |
659 | unsigned long rem, curr_addr, s_addr = (unsigned long) addr; | 664 | unsigned long rem, curr_addr, s_addr = (unsigned long) addr; |
660 | 665 | ||
661 | if (unlikely(i->type & ITER_PIPE)) | 666 | if (unlikely(iov_iter_is_pipe(i))) |
662 | return copy_pipe_to_iter_mcsafe(addr, bytes, i); | 667 | return copy_pipe_to_iter_mcsafe(addr, bytes, i); |
663 | if (iter_is_iovec(i)) | 668 | if (iter_is_iovec(i)) |
664 | might_fault(); | 669 | might_fault(); |
@@ -692,7 +697,7 @@ EXPORT_SYMBOL_GPL(_copy_to_iter_mcsafe); | |||
692 | size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) | 697 | size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) |
693 | { | 698 | { |
694 | char *to = addr; | 699 | char *to = addr; |
695 | if (unlikely(i->type & ITER_PIPE)) { | 700 | if (unlikely(iov_iter_is_pipe(i))) { |
696 | WARN_ON(1); | 701 | WARN_ON(1); |
697 | return 0; | 702 | return 0; |
698 | } | 703 | } |
@@ -712,7 +717,7 @@ EXPORT_SYMBOL(_copy_from_iter); | |||
712 | bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) | 717 | bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) |
713 | { | 718 | { |
714 | char *to = addr; | 719 | char *to = addr; |
715 | if (unlikely(i->type & ITER_PIPE)) { | 720 | if (unlikely(iov_iter_is_pipe(i))) { |
716 | WARN_ON(1); | 721 | WARN_ON(1); |
717 | return false; | 722 | return false; |
718 | } | 723 | } |
@@ -739,7 +744,7 @@ EXPORT_SYMBOL(_copy_from_iter_full); | |||
739 | size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) | 744 | size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) |
740 | { | 745 | { |
741 | char *to = addr; | 746 | char *to = addr; |
742 | if (unlikely(i->type & ITER_PIPE)) { | 747 | if (unlikely(iov_iter_is_pipe(i))) { |
743 | WARN_ON(1); | 748 | WARN_ON(1); |
744 | return 0; | 749 | return 0; |
745 | } | 750 | } |
@@ -773,7 +778,7 @@ EXPORT_SYMBOL(_copy_from_iter_nocache); | |||
773 | size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i) | 778 | size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i) |
774 | { | 779 | { |
775 | char *to = addr; | 780 | char *to = addr; |
776 | if (unlikely(i->type & ITER_PIPE)) { | 781 | if (unlikely(iov_iter_is_pipe(i))) { |
777 | WARN_ON(1); | 782 | WARN_ON(1); |
778 | return 0; | 783 | return 0; |
779 | } | 784 | } |
@@ -794,7 +799,7 @@ EXPORT_SYMBOL_GPL(_copy_from_iter_flushcache); | |||
794 | bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) | 799 | bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) |
795 | { | 800 | { |
796 | char *to = addr; | 801 | char *to = addr; |
797 | if (unlikely(i->type & ITER_PIPE)) { | 802 | if (unlikely(iov_iter_is_pipe(i))) { |
798 | WARN_ON(1); | 803 | WARN_ON(1); |
799 | return false; | 804 | return false; |
800 | } | 805 | } |
@@ -836,7 +841,9 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, | |||
836 | size_t wanted = copy_to_iter(kaddr + offset, bytes, i); | 841 | size_t wanted = copy_to_iter(kaddr + offset, bytes, i); |
837 | kunmap_atomic(kaddr); | 842 | kunmap_atomic(kaddr); |
838 | return wanted; | 843 | return wanted; |
839 | } else if (likely(!(i->type & ITER_PIPE))) | 844 | } else if (unlikely(iov_iter_is_discard(i))) |
845 | return bytes; | ||
846 | else if (likely(!iov_iter_is_pipe(i))) | ||
840 | return copy_page_to_iter_iovec(page, offset, bytes, i); | 847 | return copy_page_to_iter_iovec(page, offset, bytes, i); |
841 | else | 848 | else |
842 | return copy_page_to_iter_pipe(page, offset, bytes, i); | 849 | return copy_page_to_iter_pipe(page, offset, bytes, i); |
@@ -848,7 +855,7 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, | |||
848 | { | 855 | { |
849 | if (unlikely(!page_copy_sane(page, offset, bytes))) | 856 | if (unlikely(!page_copy_sane(page, offset, bytes))) |
850 | return 0; | 857 | return 0; |
851 | if (unlikely(i->type & ITER_PIPE)) { | 858 | if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { |
852 | WARN_ON(1); | 859 | WARN_ON(1); |
853 | return 0; | 860 | return 0; |
854 | } | 861 | } |
@@ -888,7 +895,7 @@ static size_t pipe_zero(size_t bytes, struct iov_iter *i) | |||
888 | 895 | ||
889 | size_t iov_iter_zero(size_t bytes, struct iov_iter *i) | 896 | size_t iov_iter_zero(size_t bytes, struct iov_iter *i) |
890 | { | 897 | { |
891 | if (unlikely(i->type & ITER_PIPE)) | 898 | if (unlikely(iov_iter_is_pipe(i))) |
892 | return pipe_zero(bytes, i); | 899 | return pipe_zero(bytes, i); |
893 | iterate_and_advance(i, bytes, v, | 900 | iterate_and_advance(i, bytes, v, |
894 | clear_user(v.iov_base, v.iov_len), | 901 | clear_user(v.iov_base, v.iov_len), |
@@ -908,7 +915,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, | |||
908 | kunmap_atomic(kaddr); | 915 | kunmap_atomic(kaddr); |
909 | return 0; | 916 | return 0; |
910 | } | 917 | } |
911 | if (unlikely(i->type & ITER_PIPE)) { | 918 | if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { |
912 | kunmap_atomic(kaddr); | 919 | kunmap_atomic(kaddr); |
913 | WARN_ON(1); | 920 | WARN_ON(1); |
914 | return 0; | 921 | return 0; |
@@ -972,10 +979,14 @@ static void pipe_advance(struct iov_iter *i, size_t size) | |||
972 | 979 | ||
973 | void iov_iter_advance(struct iov_iter *i, size_t size) | 980 | void iov_iter_advance(struct iov_iter *i, size_t size) |
974 | { | 981 | { |
975 | if (unlikely(i->type & ITER_PIPE)) { | 982 | if (unlikely(iov_iter_is_pipe(i))) { |
976 | pipe_advance(i, size); | 983 | pipe_advance(i, size); |
977 | return; | 984 | return; |
978 | } | 985 | } |
986 | if (unlikely(iov_iter_is_discard(i))) { | ||
987 | i->count -= size; | ||
988 | return; | ||
989 | } | ||
979 | iterate_and_advance(i, size, v, 0, 0, 0) | 990 | iterate_and_advance(i, size, v, 0, 0, 0) |
980 | } | 991 | } |
981 | EXPORT_SYMBOL(iov_iter_advance); | 992 | EXPORT_SYMBOL(iov_iter_advance); |
@@ -987,7 +998,7 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll) | |||
987 | if (WARN_ON(unroll > MAX_RW_COUNT)) | 998 | if (WARN_ON(unroll > MAX_RW_COUNT)) |
988 | return; | 999 | return; |
989 | i->count += unroll; | 1000 | i->count += unroll; |
990 | if (unlikely(i->type & ITER_PIPE)) { | 1001 | if (unlikely(iov_iter_is_pipe(i))) { |
991 | struct pipe_inode_info *pipe = i->pipe; | 1002 | struct pipe_inode_info *pipe = i->pipe; |
992 | int idx = i->idx; | 1003 | int idx = i->idx; |
993 | size_t off = i->iov_offset; | 1004 | size_t off = i->iov_offset; |
@@ -1011,12 +1022,14 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll) | |||
1011 | pipe_truncate(i); | 1022 | pipe_truncate(i); |
1012 | return; | 1023 | return; |
1013 | } | 1024 | } |
1025 | if (unlikely(iov_iter_is_discard(i))) | ||
1026 | return; | ||
1014 | if (unroll <= i->iov_offset) { | 1027 | if (unroll <= i->iov_offset) { |
1015 | i->iov_offset -= unroll; | 1028 | i->iov_offset -= unroll; |
1016 | return; | 1029 | return; |
1017 | } | 1030 | } |
1018 | unroll -= i->iov_offset; | 1031 | unroll -= i->iov_offset; |
1019 | if (i->type & ITER_BVEC) { | 1032 | if (iov_iter_is_bvec(i)) { |
1020 | const struct bio_vec *bvec = i->bvec; | 1033 | const struct bio_vec *bvec = i->bvec; |
1021 | while (1) { | 1034 | while (1) { |
1022 | size_t n = (--bvec)->bv_len; | 1035 | size_t n = (--bvec)->bv_len; |
@@ -1049,23 +1062,25 @@ EXPORT_SYMBOL(iov_iter_revert); | |||
1049 | */ | 1062 | */ |
1050 | size_t iov_iter_single_seg_count(const struct iov_iter *i) | 1063 | size_t iov_iter_single_seg_count(const struct iov_iter *i) |
1051 | { | 1064 | { |
1052 | if (unlikely(i->type & ITER_PIPE)) | 1065 | if (unlikely(iov_iter_is_pipe(i))) |
1053 | return i->count; // it is a silly place, anyway | 1066 | return i->count; // it is a silly place, anyway |
1054 | if (i->nr_segs == 1) | 1067 | if (i->nr_segs == 1) |
1055 | return i->count; | 1068 | return i->count; |
1056 | else if (i->type & ITER_BVEC) | 1069 | if (unlikely(iov_iter_is_discard(i))) |
1070 | return i->count; | ||
1071 | else if (iov_iter_is_bvec(i)) | ||
1057 | return min(i->count, i->bvec->bv_len - i->iov_offset); | 1072 | return min(i->count, i->bvec->bv_len - i->iov_offset); |
1058 | else | 1073 | else |
1059 | return min(i->count, i->iov->iov_len - i->iov_offset); | 1074 | return min(i->count, i->iov->iov_len - i->iov_offset); |
1060 | } | 1075 | } |
1061 | EXPORT_SYMBOL(iov_iter_single_seg_count); | 1076 | EXPORT_SYMBOL(iov_iter_single_seg_count); |
1062 | 1077 | ||
1063 | void iov_iter_kvec(struct iov_iter *i, int direction, | 1078 | void iov_iter_kvec(struct iov_iter *i, unsigned int direction, |
1064 | const struct kvec *kvec, unsigned long nr_segs, | 1079 | const struct kvec *kvec, unsigned long nr_segs, |
1065 | size_t count) | 1080 | size_t count) |
1066 | { | 1081 | { |
1067 | BUG_ON(!(direction & ITER_KVEC)); | 1082 | WARN_ON(direction & ~(READ | WRITE)); |
1068 | i->type = direction; | 1083 | i->type = ITER_KVEC | (direction & (READ | WRITE)); |
1069 | i->kvec = kvec; | 1084 | i->kvec = kvec; |
1070 | i->nr_segs = nr_segs; | 1085 | i->nr_segs = nr_segs; |
1071 | i->iov_offset = 0; | 1086 | i->iov_offset = 0; |
@@ -1073,12 +1088,12 @@ void iov_iter_kvec(struct iov_iter *i, int direction, | |||
1073 | } | 1088 | } |
1074 | EXPORT_SYMBOL(iov_iter_kvec); | 1089 | EXPORT_SYMBOL(iov_iter_kvec); |
1075 | 1090 | ||
1076 | void iov_iter_bvec(struct iov_iter *i, int direction, | 1091 | void iov_iter_bvec(struct iov_iter *i, unsigned int direction, |
1077 | const struct bio_vec *bvec, unsigned long nr_segs, | 1092 | const struct bio_vec *bvec, unsigned long nr_segs, |
1078 | size_t count) | 1093 | size_t count) |
1079 | { | 1094 | { |
1080 | BUG_ON(!(direction & ITER_BVEC)); | 1095 | WARN_ON(direction & ~(READ | WRITE)); |
1081 | i->type = direction; | 1096 | i->type = ITER_BVEC | (direction & (READ | WRITE)); |
1082 | i->bvec = bvec; | 1097 | i->bvec = bvec; |
1083 | i->nr_segs = nr_segs; | 1098 | i->nr_segs = nr_segs; |
1084 | i->iov_offset = 0; | 1099 | i->iov_offset = 0; |
@@ -1086,13 +1101,13 @@ void iov_iter_bvec(struct iov_iter *i, int direction, | |||
1086 | } | 1101 | } |
1087 | EXPORT_SYMBOL(iov_iter_bvec); | 1102 | EXPORT_SYMBOL(iov_iter_bvec); |
1088 | 1103 | ||
1089 | void iov_iter_pipe(struct iov_iter *i, int direction, | 1104 | void iov_iter_pipe(struct iov_iter *i, unsigned int direction, |
1090 | struct pipe_inode_info *pipe, | 1105 | struct pipe_inode_info *pipe, |
1091 | size_t count) | 1106 | size_t count) |
1092 | { | 1107 | { |
1093 | BUG_ON(direction != ITER_PIPE); | 1108 | BUG_ON(direction != READ); |
1094 | WARN_ON(pipe->nrbufs == pipe->buffers); | 1109 | WARN_ON(pipe->nrbufs == pipe->buffers); |
1095 | i->type = direction; | 1110 | i->type = ITER_PIPE | READ; |
1096 | i->pipe = pipe; | 1111 | i->pipe = pipe; |
1097 | i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); | 1112 | i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); |
1098 | i->iov_offset = 0; | 1113 | i->iov_offset = 0; |
@@ -1101,12 +1116,30 @@ void iov_iter_pipe(struct iov_iter *i, int direction, | |||
1101 | } | 1116 | } |
1102 | EXPORT_SYMBOL(iov_iter_pipe); | 1117 | EXPORT_SYMBOL(iov_iter_pipe); |
1103 | 1118 | ||
1119 | /** | ||
1120 | * iov_iter_discard - Initialise an I/O iterator that discards data | ||
1121 | * @i: The iterator to initialise. | ||
1122 | * @direction: The direction of the transfer. | ||
1123 | * @count: The size of the I/O buffer in bytes. | ||
1124 | * | ||
1125 | * Set up an I/O iterator that just discards everything that's written to it. | ||
1126 | * It's only available as a READ iterator. | ||
1127 | */ | ||
1128 | void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count) | ||
1129 | { | ||
1130 | BUG_ON(direction != READ); | ||
1131 | i->type = ITER_DISCARD | READ; | ||
1132 | i->count = count; | ||
1133 | i->iov_offset = 0; | ||
1134 | } | ||
1135 | EXPORT_SYMBOL(iov_iter_discard); | ||
1136 | |||
1104 | unsigned long iov_iter_alignment(const struct iov_iter *i) | 1137 | unsigned long iov_iter_alignment(const struct iov_iter *i) |
1105 | { | 1138 | { |
1106 | unsigned long res = 0; | 1139 | unsigned long res = 0; |
1107 | size_t size = i->count; | 1140 | size_t size = i->count; |
1108 | 1141 | ||
1109 | if (unlikely(i->type & ITER_PIPE)) { | 1142 | if (unlikely(iov_iter_is_pipe(i))) { |
1110 | if (size && i->iov_offset && allocated(&i->pipe->bufs[i->idx])) | 1143 | if (size && i->iov_offset && allocated(&i->pipe->bufs[i->idx])) |
1111 | return size | i->iov_offset; | 1144 | return size | i->iov_offset; |
1112 | return size; | 1145 | return size; |
@@ -1125,7 +1158,7 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i) | |||
1125 | unsigned long res = 0; | 1158 | unsigned long res = 0; |
1126 | size_t size = i->count; | 1159 | size_t size = i->count; |
1127 | 1160 | ||
1128 | if (unlikely(i->type & ITER_PIPE)) { | 1161 | if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { |
1129 | WARN_ON(1); | 1162 | WARN_ON(1); |
1130 | return ~0U; | 1163 | return ~0U; |
1131 | } | 1164 | } |
@@ -1193,8 +1226,11 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, | |||
1193 | if (maxsize > i->count) | 1226 | if (maxsize > i->count) |
1194 | maxsize = i->count; | 1227 | maxsize = i->count; |
1195 | 1228 | ||
1196 | if (unlikely(i->type & ITER_PIPE)) | 1229 | if (unlikely(iov_iter_is_pipe(i))) |
1197 | return pipe_get_pages(i, pages, maxsize, maxpages, start); | 1230 | return pipe_get_pages(i, pages, maxsize, maxpages, start); |
1231 | if (unlikely(iov_iter_is_discard(i))) | ||
1232 | return -EFAULT; | ||
1233 | |||
1198 | iterate_all_kinds(i, maxsize, v, ({ | 1234 | iterate_all_kinds(i, maxsize, v, ({ |
1199 | unsigned long addr = (unsigned long)v.iov_base; | 1235 | unsigned long addr = (unsigned long)v.iov_base; |
1200 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); | 1236 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); |
@@ -1205,7 +1241,7 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, | |||
1205 | len = maxpages * PAGE_SIZE; | 1241 | len = maxpages * PAGE_SIZE; |
1206 | addr &= ~(PAGE_SIZE - 1); | 1242 | addr &= ~(PAGE_SIZE - 1); |
1207 | n = DIV_ROUND_UP(len, PAGE_SIZE); | 1243 | n = DIV_ROUND_UP(len, PAGE_SIZE); |
1208 | res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages); | 1244 | res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, pages); |
1209 | if (unlikely(res < 0)) | 1245 | if (unlikely(res < 0)) |
1210 | return res; | 1246 | return res; |
1211 | return (res == n ? len : res * PAGE_SIZE) - *start; | 1247 | return (res == n ? len : res * PAGE_SIZE) - *start; |
@@ -1270,8 +1306,11 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, | |||
1270 | if (maxsize > i->count) | 1306 | if (maxsize > i->count) |
1271 | maxsize = i->count; | 1307 | maxsize = i->count; |
1272 | 1308 | ||
1273 | if (unlikely(i->type & ITER_PIPE)) | 1309 | if (unlikely(iov_iter_is_pipe(i))) |
1274 | return pipe_get_pages_alloc(i, pages, maxsize, start); | 1310 | return pipe_get_pages_alloc(i, pages, maxsize, start); |
1311 | if (unlikely(iov_iter_is_discard(i))) | ||
1312 | return -EFAULT; | ||
1313 | |||
1275 | iterate_all_kinds(i, maxsize, v, ({ | 1314 | iterate_all_kinds(i, maxsize, v, ({ |
1276 | unsigned long addr = (unsigned long)v.iov_base; | 1315 | unsigned long addr = (unsigned long)v.iov_base; |
1277 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); | 1316 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); |
@@ -1283,7 +1322,7 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, | |||
1283 | p = get_pages_array(n); | 1322 | p = get_pages_array(n); |
1284 | if (!p) | 1323 | if (!p) |
1285 | return -ENOMEM; | 1324 | return -ENOMEM; |
1286 | res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, p); | 1325 | res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, p); |
1287 | if (unlikely(res < 0)) { | 1326 | if (unlikely(res < 0)) { |
1288 | kvfree(p); | 1327 | kvfree(p); |
1289 | return res; | 1328 | return res; |
@@ -1313,7 +1352,7 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, | |||
1313 | __wsum sum, next; | 1352 | __wsum sum, next; |
1314 | size_t off = 0; | 1353 | size_t off = 0; |
1315 | sum = *csum; | 1354 | sum = *csum; |
1316 | if (unlikely(i->type & ITER_PIPE)) { | 1355 | if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { |
1317 | WARN_ON(1); | 1356 | WARN_ON(1); |
1318 | return 0; | 1357 | return 0; |
1319 | } | 1358 | } |
@@ -1355,7 +1394,7 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, | |||
1355 | __wsum sum, next; | 1394 | __wsum sum, next; |
1356 | size_t off = 0; | 1395 | size_t off = 0; |
1357 | sum = *csum; | 1396 | sum = *csum; |
1358 | if (unlikely(i->type & ITER_PIPE)) { | 1397 | if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { |
1359 | WARN_ON(1); | 1398 | WARN_ON(1); |
1360 | return false; | 1399 | return false; |
1361 | } | 1400 | } |
@@ -1400,7 +1439,7 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, | |||
1400 | __wsum sum, next; | 1439 | __wsum sum, next; |
1401 | size_t off = 0; | 1440 | size_t off = 0; |
1402 | sum = *csum; | 1441 | sum = *csum; |
1403 | if (unlikely(i->type & ITER_PIPE)) { | 1442 | if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { |
1404 | WARN_ON(1); /* for now */ | 1443 | WARN_ON(1); /* for now */ |
1405 | return 0; | 1444 | return 0; |
1406 | } | 1445 | } |
@@ -1442,8 +1481,10 @@ int iov_iter_npages(const struct iov_iter *i, int maxpages) | |||
1442 | 1481 | ||
1443 | if (!size) | 1482 | if (!size) |
1444 | return 0; | 1483 | return 0; |
1484 | if (unlikely(iov_iter_is_discard(i))) | ||
1485 | return 0; | ||
1445 | 1486 | ||
1446 | if (unlikely(i->type & ITER_PIPE)) { | 1487 | if (unlikely(iov_iter_is_pipe(i))) { |
1447 | struct pipe_inode_info *pipe = i->pipe; | 1488 | struct pipe_inode_info *pipe = i->pipe; |
1448 | size_t off; | 1489 | size_t off; |
1449 | int idx; | 1490 | int idx; |
@@ -1481,11 +1522,13 @@ EXPORT_SYMBOL(iov_iter_npages); | |||
1481 | const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) | 1522 | const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) |
1482 | { | 1523 | { |
1483 | *new = *old; | 1524 | *new = *old; |
1484 | if (unlikely(new->type & ITER_PIPE)) { | 1525 | if (unlikely(iov_iter_is_pipe(new))) { |
1485 | WARN_ON(1); | 1526 | WARN_ON(1); |
1486 | return NULL; | 1527 | return NULL; |
1487 | } | 1528 | } |
1488 | if (new->type & ITER_BVEC) | 1529 | if (unlikely(iov_iter_is_discard(new))) |
1530 | return NULL; | ||
1531 | if (iov_iter_is_bvec(new)) | ||
1489 | return new->bvec = kmemdup(new->bvec, | 1532 | return new->bvec = kmemdup(new->bvec, |
1490 | new->nr_segs * sizeof(struct bio_vec), | 1533 | new->nr_segs * sizeof(struct bio_vec), |
1491 | flags); | 1534 | flags); |
diff --git a/mm/filemap.c b/mm/filemap.c index 218d0b2ec82d..1fe6c4c37a35 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -2049,7 +2049,7 @@ find_page: | |||
2049 | !mapping->a_ops->is_partially_uptodate) | 2049 | !mapping->a_ops->is_partially_uptodate) |
2050 | goto page_not_up_to_date; | 2050 | goto page_not_up_to_date; |
2051 | /* pipes can't handle partially uptodate pages */ | 2051 | /* pipes can't handle partially uptodate pages */ |
2052 | if (unlikely(iter->type & ITER_PIPE)) | 2052 | if (unlikely(iov_iter_is_pipe(iter))) |
2053 | goto page_not_up_to_date; | 2053 | goto page_not_up_to_date; |
2054 | if (!trylock_page(page)) | 2054 | if (!trylock_page(page)) |
2055 | goto page_not_up_to_date; | 2055 | goto page_not_up_to_date; |
diff --git a/mm/page_io.c b/mm/page_io.c index a451ffa9491c..27b835728442 100644 --- a/mm/page_io.c +++ b/mm/page_io.c | |||
@@ -294,7 +294,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, | |||
294 | }; | 294 | }; |
295 | struct iov_iter from; | 295 | struct iov_iter from; |
296 | 296 | ||
297 | iov_iter_bvec(&from, ITER_BVEC | WRITE, &bv, 1, PAGE_SIZE); | 297 | iov_iter_bvec(&from, WRITE, &bv, 1, PAGE_SIZE); |
298 | init_sync_kiocb(&kiocb, swap_file); | 298 | init_sync_kiocb(&kiocb, swap_file); |
299 | kiocb.ki_pos = page_file_offset(page); | 299 | kiocb.ki_pos = page_file_offset(page); |
300 | 300 | ||
diff --git a/net/9p/client.c b/net/9p/client.c index 5f23e18eecc0..2c9a17b9b46b 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -2066,7 +2066,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | |||
2066 | struct kvec kv = {.iov_base = data, .iov_len = count}; | 2066 | struct kvec kv = {.iov_base = data, .iov_len = count}; |
2067 | struct iov_iter to; | 2067 | struct iov_iter to; |
2068 | 2068 | ||
2069 | iov_iter_kvec(&to, READ | ITER_KVEC, &kv, 1, count); | 2069 | iov_iter_kvec(&to, READ, &kv, 1, count); |
2070 | 2070 | ||
2071 | p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", | 2071 | p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", |
2072 | fid->fid, (unsigned long long) offset, count); | 2072 | fid->fid, (unsigned long long) offset, count); |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index eb596c2ed546..91981970f542 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -329,7 +329,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, | |||
329 | if (!iov_iter_count(data)) | 329 | if (!iov_iter_count(data)) |
330 | return 0; | 330 | return 0; |
331 | 331 | ||
332 | if (!(data->type & ITER_KVEC)) { | 332 | if (iov_iter_is_kvec(data)) { |
333 | int n; | 333 | int n; |
334 | /* | 334 | /* |
335 | * We allow only p9_max_pages pinned. We wait for the | 335 | * We allow only p9_max_pages pinned. We wait for the |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 4e2576fc0c59..828e87fe8027 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -467,7 +467,7 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, | |||
467 | iv.iov_len = skb->len; | 467 | iv.iov_len = skb->len; |
468 | 468 | ||
469 | memset(&msg, 0, sizeof(msg)); | 469 | memset(&msg, 0, sizeof(msg)); |
470 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len); | 470 | iov_iter_kvec(&msg.msg_iter, WRITE, &iv, 1, skb->len); |
471 | 471 | ||
472 | err = l2cap_chan_send(chan, &msg, skb->len); | 472 | err = l2cap_chan_send(chan, &msg, skb->len); |
473 | if (err > 0) { | 473 | if (err > 0) { |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 51c2cf2d8923..58fc6333d412 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -63,7 +63,7 @@ static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *dat | |||
63 | 63 | ||
64 | memset(&msg, 0, sizeof(msg)); | 64 | memset(&msg, 0, sizeof(msg)); |
65 | 65 | ||
66 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, total_len); | 66 | iov_iter_kvec(&msg.msg_iter, WRITE, &iv, 1, total_len); |
67 | 67 | ||
68 | l2cap_chan_send(chan, &msg, total_len); | 68 | l2cap_chan_send(chan, &msg, total_len); |
69 | 69 | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index a1c1b7e8a45c..c822e626761b 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -622,7 +622,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) | |||
622 | 622 | ||
623 | memset(&msg, 0, sizeof(msg)); | 623 | memset(&msg, 0, sizeof(msg)); |
624 | 624 | ||
625 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iv, 2, 1 + len); | 625 | iov_iter_kvec(&msg.msg_iter, WRITE, iv, 2, 1 + len); |
626 | 626 | ||
627 | l2cap_chan_send(chan, &msg, 1 + len); | 627 | l2cap_chan_send(chan, &msg, 1 + len); |
628 | 628 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 88e35830198c..57fcc6b4bf6e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -513,7 +513,7 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len) | |||
513 | if (!buf) | 513 | if (!buf) |
514 | msg.msg_flags |= MSG_TRUNC; | 514 | msg.msg_flags |= MSG_TRUNC; |
515 | 515 | ||
516 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, len); | 516 | iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, len); |
517 | r = sock_recvmsg(sock, &msg, msg.msg_flags); | 517 | r = sock_recvmsg(sock, &msg, msg.msg_flags); |
518 | if (r == -EAGAIN) | 518 | if (r == -EAGAIN) |
519 | r = 0; | 519 | r = 0; |
@@ -532,7 +532,7 @@ static int ceph_tcp_recvpage(struct socket *sock, struct page *page, | |||
532 | int r; | 532 | int r; |
533 | 533 | ||
534 | BUG_ON(page_offset + length > PAGE_SIZE); | 534 | BUG_ON(page_offset + length > PAGE_SIZE); |
535 | iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, &bvec, 1, length); | 535 | iov_iter_bvec(&msg.msg_iter, READ, &bvec, 1, length); |
536 | r = sock_recvmsg(sock, &msg, msg.msg_flags); | 536 | r = sock_recvmsg(sock, &msg, msg.msg_flags); |
537 | if (r == -EAGAIN) | 537 | if (r == -EAGAIN) |
538 | r = 0; | 538 | r = 0; |
@@ -594,7 +594,7 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, | |||
594 | else | 594 | else |
595 | msg.msg_flags |= MSG_EOR; /* superfluous, but what the hell */ | 595 | msg.msg_flags |= MSG_EOR; /* superfluous, but what the hell */ |
596 | 596 | ||
597 | iov_iter_bvec(&msg.msg_iter, WRITE | ITER_BVEC, &bvec, 1, size); | 597 | iov_iter_bvec(&msg.msg_iter, WRITE, &bvec, 1, size); |
598 | ret = sock_sendmsg(sock, &msg); | 598 | ret = sock_sendmsg(sock, &msg); |
599 | if (ret == -EAGAIN) | 599 | if (ret == -EAGAIN) |
600 | ret = 0; | 600 | ret = 0; |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index d4020c5e831d..2526be6b3d90 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -1616,7 +1616,7 @@ ip_vs_receive(struct socket *sock, char *buffer, const size_t buflen) | |||
1616 | EnterFunction(7); | 1616 | EnterFunction(7); |
1617 | 1617 | ||
1618 | /* Receive a packet */ | 1618 | /* Receive a packet */ |
1619 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, buflen); | 1619 | iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, buflen); |
1620 | len = sock_recvmsg(sock, &msg, MSG_DONTWAIT); | 1620 | len = sock_recvmsg(sock, &msg, MSG_DONTWAIT); |
1621 | if (len < 0) | 1621 | if (len < 0) |
1622 | return len; | 1622 | return len; |
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c index 52241d679cc9..89c3a8c7859a 100644 --- a/net/smc/smc_clc.c +++ b/net/smc/smc_clc.c | |||
@@ -286,7 +286,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, | |||
286 | */ | 286 | */ |
287 | krflags = MSG_PEEK | MSG_WAITALL; | 287 | krflags = MSG_PEEK | MSG_WAITALL; |
288 | smc->clcsock->sk->sk_rcvtimeo = CLC_WAIT_TIME; | 288 | smc->clcsock->sk->sk_rcvtimeo = CLC_WAIT_TIME; |
289 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &vec, 1, | 289 | iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, |
290 | sizeof(struct smc_clc_msg_hdr)); | 290 | sizeof(struct smc_clc_msg_hdr)); |
291 | len = sock_recvmsg(smc->clcsock, &msg, krflags); | 291 | len = sock_recvmsg(smc->clcsock, &msg, krflags); |
292 | if (signal_pending(current)) { | 292 | if (signal_pending(current)) { |
@@ -325,7 +325,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, | |||
325 | 325 | ||
326 | /* receive the complete CLC message */ | 326 | /* receive the complete CLC message */ |
327 | memset(&msg, 0, sizeof(struct msghdr)); | 327 | memset(&msg, 0, sizeof(struct msghdr)); |
328 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &vec, 1, datlen); | 328 | iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, datlen); |
329 | krflags = MSG_WAITALL; | 329 | krflags = MSG_WAITALL; |
330 | len = sock_recvmsg(smc->clcsock, &msg, krflags); | 330 | len = sock_recvmsg(smc->clcsock, &msg, krflags); |
331 | if (len < datlen || !smc_clc_msg_hdr_valid(clcm)) { | 331 | if (len < datlen || !smc_clc_msg_hdr_valid(clcm)) { |
diff --git a/net/socket.c b/net/socket.c index 99c96851469f..593826e11a53 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -635,7 +635,7 @@ EXPORT_SYMBOL(sock_sendmsg); | |||
635 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | 635 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, |
636 | struct kvec *vec, size_t num, size_t size) | 636 | struct kvec *vec, size_t num, size_t size) |
637 | { | 637 | { |
638 | iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); | 638 | iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size); |
639 | return sock_sendmsg(sock, msg); | 639 | return sock_sendmsg(sock, msg); |
640 | } | 640 | } |
641 | EXPORT_SYMBOL(kernel_sendmsg); | 641 | EXPORT_SYMBOL(kernel_sendmsg); |
@@ -648,7 +648,7 @@ int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, | |||
648 | if (!sock->ops->sendmsg_locked) | 648 | if (!sock->ops->sendmsg_locked) |
649 | return sock_no_sendmsg_locked(sk, msg, size); | 649 | return sock_no_sendmsg_locked(sk, msg, size); |
650 | 650 | ||
651 | iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); | 651 | iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size); |
652 | 652 | ||
653 | return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg)); | 653 | return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg)); |
654 | } | 654 | } |
@@ -823,7 +823,7 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg, | |||
823 | mm_segment_t oldfs = get_fs(); | 823 | mm_segment_t oldfs = get_fs(); |
824 | int result; | 824 | int result; |
825 | 825 | ||
826 | iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size); | 826 | iov_iter_kvec(&msg->msg_iter, READ, vec, num, size); |
827 | set_fs(KERNEL_DS); | 827 | set_fs(KERNEL_DS); |
828 | result = sock_recvmsg(sock, msg, flags); | 828 | result = sock_recvmsg(sock, msg, flags); |
829 | set_fs(oldfs); | 829 | set_fs(oldfs); |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 3b525accaa68..986f3ed7d1a2 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -336,7 +336,7 @@ static ssize_t svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, | |||
336 | rqstp->rq_xprt_hlen = 0; | 336 | rqstp->rq_xprt_hlen = 0; |
337 | 337 | ||
338 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 338 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
339 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, nr, buflen); | 339 | iov_iter_kvec(&msg.msg_iter, READ, iov, nr, buflen); |
340 | if (base != 0) { | 340 | if (base != 0) { |
341 | iov_iter_advance(&msg.msg_iter, base); | 341 | iov_iter_advance(&msg.msg_iter, base); |
342 | buflen -= base; | 342 | buflen -= base; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 1b51e04d3566..ae77c71c1f64 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -361,7 +361,7 @@ static ssize_t | |||
361 | xs_read_kvec(struct socket *sock, struct msghdr *msg, int flags, | 361 | xs_read_kvec(struct socket *sock, struct msghdr *msg, int flags, |
362 | struct kvec *kvec, size_t count, size_t seek) | 362 | struct kvec *kvec, size_t count, size_t seek) |
363 | { | 363 | { |
364 | iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, kvec, 1, count); | 364 | iov_iter_kvec(&msg->msg_iter, READ, kvec, 1, count); |
365 | return xs_sock_recvmsg(sock, msg, flags, seek); | 365 | return xs_sock_recvmsg(sock, msg, flags, seek); |
366 | } | 366 | } |
367 | 367 | ||
@@ -370,7 +370,7 @@ xs_read_bvec(struct socket *sock, struct msghdr *msg, int flags, | |||
370 | struct bio_vec *bvec, unsigned long nr, size_t count, | 370 | struct bio_vec *bvec, unsigned long nr, size_t count, |
371 | size_t seek) | 371 | size_t seek) |
372 | { | 372 | { |
373 | iov_iter_bvec(&msg->msg_iter, READ | ITER_BVEC, bvec, nr, count); | 373 | iov_iter_bvec(&msg->msg_iter, READ, bvec, nr, count); |
374 | return xs_sock_recvmsg(sock, msg, flags, seek); | 374 | return xs_sock_recvmsg(sock, msg, flags, seek); |
375 | } | 375 | } |
376 | 376 | ||
diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index 4bdea0057171..efb16f69bd2c 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c | |||
@@ -394,7 +394,7 @@ static int tipc_conn_rcv_from_sock(struct tipc_conn *con) | |||
394 | iov.iov_base = &s; | 394 | iov.iov_base = &s; |
395 | iov.iov_len = sizeof(s); | 395 | iov.iov_len = sizeof(s); |
396 | msg.msg_name = NULL; | 396 | msg.msg_name = NULL; |
397 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, iov.iov_len); | 397 | iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, iov.iov_len); |
398 | ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT); | 398 | ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT); |
399 | if (ret == -EWOULDBLOCK) | 399 | if (ret == -EWOULDBLOCK) |
400 | return -EWOULDBLOCK; | 400 | return -EWOULDBLOCK; |
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index 276edbc04f38..d753e362d2d9 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c | |||
@@ -489,7 +489,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page, | |||
489 | 489 | ||
490 | iov.iov_base = kaddr + offset; | 490 | iov.iov_base = kaddr + offset; |
491 | iov.iov_len = size; | 491 | iov.iov_len = size; |
492 | iov_iter_kvec(&msg_iter, WRITE | ITER_KVEC, &iov, 1, size); | 492 | iov_iter_kvec(&msg_iter, WRITE, &iov, 1, size); |
493 | rc = tls_push_data(sk, &msg_iter, size, | 493 | rc = tls_push_data(sk, &msg_iter, size, |
494 | flags, TLS_RECORD_TYPE_DATA); | 494 | flags, TLS_RECORD_TYPE_DATA); |
495 | kunmap(page); | 495 | kunmap(page); |
@@ -538,7 +538,7 @@ static int tls_device_push_pending_record(struct sock *sk, int flags) | |||
538 | { | 538 | { |
539 | struct iov_iter msg_iter; | 539 | struct iov_iter msg_iter; |
540 | 540 | ||
541 | iov_iter_kvec(&msg_iter, WRITE | ITER_KVEC, NULL, 0, 0); | 541 | iov_iter_kvec(&msg_iter, WRITE, NULL, 0, 0); |
542 | return tls_push_data(sk, &msg_iter, 0, flags, TLS_RECORD_TYPE_DATA); | 542 | return tls_push_data(sk, &msg_iter, 0, flags, TLS_RECORD_TYPE_DATA); |
543 | } | 543 | } |
544 | 544 | ||
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 5cd88ba8acd1..7b1af8b59cd2 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c | |||
@@ -799,7 +799,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) | |||
799 | struct crypto_tfm *tfm = crypto_aead_tfm(ctx->aead_send); | 799 | struct crypto_tfm *tfm = crypto_aead_tfm(ctx->aead_send); |
800 | bool async_capable = tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC; | 800 | bool async_capable = tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC; |
801 | unsigned char record_type = TLS_RECORD_TYPE_DATA; | 801 | unsigned char record_type = TLS_RECORD_TYPE_DATA; |
802 | bool is_kvec = msg->msg_iter.type & ITER_KVEC; | 802 | bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); |
803 | bool eor = !(msg->msg_flags & MSG_MORE); | 803 | bool eor = !(msg->msg_flags & MSG_MORE); |
804 | size_t try_to_copy, copied = 0; | 804 | size_t try_to_copy, copied = 0; |
805 | struct sk_msg *msg_pl, *msg_en; | 805 | struct sk_msg *msg_pl, *msg_en; |
@@ -1457,7 +1457,7 @@ int tls_sw_recvmsg(struct sock *sk, | |||
1457 | bool cmsg = false; | 1457 | bool cmsg = false; |
1458 | int target, err = 0; | 1458 | int target, err = 0; |
1459 | long timeo; | 1459 | long timeo; |
1460 | bool is_kvec = msg->msg_iter.type & ITER_KVEC; | 1460 | bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); |
1461 | int num_async = 0; | 1461 | int num_async = 0; |
1462 | 1462 | ||
1463 | flags |= nonblock; | 1463 | flags |= nonblock; |