提交 9931a07d 编写于 作者: L Linus Torvalds

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
  ...
......@@ -1256,7 +1256,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
/*
* success
*/
if (((iter->type & WRITE) && (!map_data || !map_data->null_mapped)) ||
if ((iov_iter_rw(iter) == WRITE && (!map_data || !map_data->null_mapped)) ||
(map_data && map_data->from_user)) {
ret = bio_copy_from_iter(bio, iter);
if (ret)
......
......@@ -1856,7 +1856,7 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock,
/* THINK if (signal_pending) return ... ? */
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1, size);
iov_iter_kvec(&msg.msg_iter, WRITE, &iov, 1, size);
if (sock == connection->data.socket) {
rcu_read_lock();
......
......@@ -516,7 +516,7 @@ static int drbd_recv_short(struct socket *sock, void *buf, size_t size, int flag
struct msghdr msg = {
.msg_flags = (flags ? flags : MSG_WAITALL | MSG_NOSIGNAL)
};
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, size);
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, size);
return sock_recvmsg(sock, &msg, msg.msg_flags);
}
......
......@@ -269,7 +269,7 @@ static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos)
struct iov_iter i;
ssize_t bw;
iov_iter_bvec(&i, ITER_BVEC | WRITE, bvec, 1, bvec->bv_len);
iov_iter_bvec(&i, WRITE, bvec, 1, bvec->bv_len);
file_start_write(file);
bw = vfs_iter_write(file, &i, ppos, 0);
......@@ -347,7 +347,7 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq,
ssize_t len;
rq_for_each_segment(bvec, rq, iter) {
iov_iter_bvec(&i, ITER_BVEC, &bvec, 1, bvec.bv_len);
iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len);
len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0);
if (len < 0)
return len;
......@@ -388,7 +388,7 @@ static int lo_read_transfer(struct loop_device *lo, struct request *rq,
b.bv_offset = 0;
b.bv_len = bvec.bv_len;
iov_iter_bvec(&i, ITER_BVEC, &b, 1, b.bv_len);
iov_iter_bvec(&i, READ, &b, 1, b.bv_len);
len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0);
if (len < 0) {
ret = len;
......@@ -555,8 +555,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
}
atomic_set(&cmd->ref, 2);
iov_iter_bvec(&iter, ITER_BVEC | rw, bvec,
segments, blk_rq_bytes(rq));
iov_iter_bvec(&iter, rw, bvec, segments, blk_rq_bytes(rq));
iter.iov_offset = offset;
cmd->iocb.ki_pos = pos;
......
......@@ -473,7 +473,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
u32 nbd_cmd_flags = 0;
int sent = nsock->sent, skip = 0;
iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request));
iov_iter_kvec(&from, WRITE, &iov, 1, sizeof(request));
switch (req_op(req)) {
case REQ_OP_DISCARD:
......@@ -564,8 +564,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n",
req, bvec.bv_len);
iov_iter_bvec(&from, ITER_BVEC | WRITE,
&bvec, 1, bvec.bv_len);
iov_iter_bvec(&from, WRITE, &bvec, 1, bvec.bv_len);
if (skip) {
if (skip >= iov_iter_count(&from)) {
skip -= iov_iter_count(&from);
......@@ -624,7 +623,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
int ret = 0;
reply.magic = 0;
iov_iter_kvec(&to, READ | ITER_KVEC, &iov, 1, sizeof(reply));
iov_iter_kvec(&to, READ, &iov, 1, sizeof(reply));
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
if (result <= 0) {
if (!nbd_disconnected(config))
......@@ -678,8 +677,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
struct bio_vec bvec;
rq_for_each_segment(bvec, req, iter) {
iov_iter_bvec(&to, ITER_BVEC | READ,
&bvec, 1, bvec.bv_len);
iov_iter_bvec(&to, READ, &bvec, 1, bvec.bv_len);
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
if (result <= 0) {
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)
for (i = 0; i < config->num_connections; i++) {
struct nbd_sock *nsock = config->socks[i];
iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request));
iov_iter_kvec(&from, WRITE, &iov, 1, sizeof(request));
mutex_lock(&nsock->tx_lock);
ret = sock_xmit(nbd, i, 1, &from, 0, NULL);
if (ret <= 0)
......
......@@ -638,7 +638,7 @@ static void sbefifo_collect_async_ffdc(struct sbefifo *sbefifo)
}
ffdc_iov.iov_base = ffdc;
ffdc_iov.iov_len = SBEFIFO_MAX_FFDC_SIZE;
iov_iter_kvec(&ffdc_iter, WRITE | ITER_KVEC, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE);
iov_iter_kvec(&ffdc_iter, WRITE, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE);
cmd[0] = cpu_to_be32(2);
cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_SBE_FFDC);
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,
rbytes = (*resp_len) * sizeof(__be32);
resp_iov.iov_base = response;
resp_iov.iov_len = rbytes;
iov_iter_kvec(&resp_iter, WRITE | ITER_KVEC, &resp_iov, 1, rbytes);
iov_iter_kvec(&resp_iter, WRITE, &resp_iov, 1, rbytes);
/* Perform the command */
mutex_lock(&sbefifo->lock);
......
......@@ -40,8 +40,6 @@
#define LITTLEENDIAN_CPU
#endif
#undef READ
#undef WRITE
#undef FRAME_SIZE
#define dm_output_to_console(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__)
......
......@@ -718,8 +718,7 @@ l1oip_socket_thread(void *data)
printk(KERN_DEBUG "%s: socket created and open\n",
__func__);
while (!signal_pending(current)) {
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1,
recvbuf_size);
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, recvbuf_size);
recvlen = sock_recvmsg(socket, &msg, 0);
if (recvlen > 0) {
l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen);
......
......@@ -3030,7 +3030,7 @@ ssize_t vmci_qpair_enqueue(struct vmci_qp *qpair,
if (!qpair || !buf)
return VMCI_ERROR_INVALID_ARGS;
iov_iter_kvec(&from, WRITE | ITER_KVEC, &v, 1, buf_size);
iov_iter_kvec(&from, WRITE, &v, 1, buf_size);
qp_lock(qpair);
......@@ -3074,7 +3074,7 @@ ssize_t vmci_qpair_dequeue(struct vmci_qp *qpair,
if (!qpair || !buf)
return VMCI_ERROR_INVALID_ARGS;
iov_iter_kvec(&to, READ | ITER_KVEC, &v, 1, buf_size);
iov_iter_kvec(&to, READ, &v, 1, buf_size);
qp_lock(qpair);
......@@ -3119,7 +3119,7 @@ ssize_t vmci_qpair_peek(struct vmci_qp *qpair,
if (!qpair || !buf)
return VMCI_ERROR_INVALID_ARGS;
iov_iter_kvec(&to, READ | ITER_KVEC, &v, 1, buf_size);
iov_iter_kvec(&to, READ, &v, 1, buf_size);
qp_lock(qpair);
......
......@@ -101,7 +101,7 @@ static ssize_t nvmet_file_submit_bvec(struct nvmet_req *req, loff_t pos,
rw = READ;
}
iov_iter_bvec(&iter, ITER_BVEC | rw, req->f.bvec, nr_segs, count);
iov_iter_bvec(&iter, rw, req->f.bvec, nr_segs, count);
iocb->ki_pos = pos;
iocb->ki_filp = req->ns->file;
......
......@@ -1245,8 +1245,7 @@ static int iscsit_do_rx_data(
return -1;
memset(&msg, 0, sizeof(struct msghdr));
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC,
count->iov, count->iov_count, data);
iov_iter_kvec(&msg.msg_iter, READ, count->iov, count->iov_count, data);
while (msg_data_left(&msg)) {
rx_loop = sock_recvmsg(conn->sock, &msg, MSG_WAITALL);
......@@ -1302,8 +1301,7 @@ int tx_data(
memset(&msg, 0, sizeof(struct msghdr));
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC,
iov, iov_count, data);
iov_iter_kvec(&msg.msg_iter, WRITE, iov, iov_count, data);
while (msg_data_left(&msg)) {
int tx_loop = sock_sendmsg(conn->sock, &msg);
......
......@@ -303,7 +303,7 @@ fd_execute_rw_aio(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
len += sg->length;
}
iov_iter_bvec(&iter, ITER_BVEC | is_write, bvec, sgl_nents, len);
iov_iter_bvec(&iter, is_write, bvec, sgl_nents, len);
aio_cmd->cmd = cmd;
aio_cmd->len = len;
......@@ -353,7 +353,7 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
len += sg->length;
}
iov_iter_bvec(&iter, ITER_BVEC, bvec, sgl_nents, len);
iov_iter_bvec(&iter, READ, bvec, sgl_nents, len);
if (is_write)
ret = vfs_iter_write(fd, &iter, &pos, 0);
else
......@@ -490,7 +490,7 @@ fd_execute_write_same(struct se_cmd *cmd)
len += se_dev->dev_attrib.block_size;
}
iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len);
iov_iter_bvec(&iter, READ, bvec, nolb, len);
ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos, 0);
kfree(bvec);
......
......@@ -309,7 +309,7 @@ int usbip_recv(struct socket *sock, void *buf, int size)
if (!sock || !buf || !size)
return -EINVAL;
iov_iter_kvec(&msg.msg_iter, READ|ITER_KVEC, &iov, 1, size);
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, size);
usbip_dbg_xmit("enter\n");
......
......@@ -137,13 +137,13 @@ static void pvcalls_conn_back_read(void *opaque)
if (masked_prod < masked_cons) {
vec[0].iov_base = data->in + masked_prod;
vec[0].iov_len = wanted;
iov_iter_kvec(&msg.msg_iter, ITER_KVEC|WRITE, vec, 1, wanted);
iov_iter_kvec(&msg.msg_iter, WRITE, vec, 1, wanted);
} else {
vec[0].iov_base = data->in + masked_prod;
vec[0].iov_len = array_size - masked_prod;
vec[1].iov_base = data->in;
vec[1].iov_len = wanted - vec[0].iov_len;
iov_iter_kvec(&msg.msg_iter, ITER_KVEC|WRITE, vec, 2, wanted);
iov_iter_kvec(&msg.msg_iter, WRITE, vec, 2, wanted);
}
atomic_set(&map->read, 0);
......@@ -195,13 +195,13 @@ static void pvcalls_conn_back_write(struct sock_mapping *map)
if (pvcalls_mask(prod, array_size) > pvcalls_mask(cons, array_size)) {
vec[0].iov_base = data->out + pvcalls_mask(cons, array_size);
vec[0].iov_len = size;
iov_iter_kvec(&msg.msg_iter, ITER_KVEC|READ, vec, 1, size);
iov_iter_kvec(&msg.msg_iter, READ, vec, 1, size);
} else {
vec[0].iov_base = data->out + pvcalls_mask(cons, array_size);
vec[0].iov_len = array_size - pvcalls_mask(cons, array_size);
vec[1].iov_base = data->out;
vec[1].iov_len = size - vec[0].iov_len;
iov_iter_kvec(&msg.msg_iter, ITER_KVEC|READ, vec, 2, size);
iov_iter_kvec(&msg.msg_iter, READ, vec, 2, size);
}
atomic_set(&map->write, 0);
......
......@@ -65,7 +65,7 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
if (retval == 0)
return retval;
iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE);
iov_iter_bvec(&to, READ, &bvec, 1, PAGE_SIZE);
retval = p9_client_read(fid, page_offset(page), &to, &err);
if (err) {
......@@ -175,7 +175,7 @@ static int v9fs_vfs_writepage_locked(struct page *page)
bvec.bv_page = page;
bvec.bv_offset = 0;
bvec.bv_len = len;
iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len);
iov_iter_bvec(&from, WRITE, &bvec, 1, len);
/* We should have writeback_fid always set */
BUG_ON(!v9inode->writeback_fid);
......
......@@ -123,7 +123,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
if (rdir->tail == rdir->head) {
struct iov_iter to;
int n;
iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen);
iov_iter_kvec(&to, READ, &kvec, 1, buflen);
n = p9_client_read(file->private_data, ctx->pos, &to,
&err);
if (err)
......
......@@ -32,7 +32,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
struct iov_iter to;
int err;
iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size);
iov_iter_kvec(&to, READ, &kvec, 1, buffer_size);
attr_fid = p9_client_xattrwalk(fid, name, &attr_size);
if (IS_ERR(attr_fid)) {
......@@ -107,7 +107,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
struct iov_iter from;
int retval, err;
iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len);
iov_iter_kvec(&from, WRITE, &kvec, 1, value_len);
p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n",
name, value_len, flags);
......
......@@ -27,3 +27,15 @@ config AFS_FSCACHE
help
Say Y here if you want AFS data to be cached locally on disk through
the generic filesystem cache manager
config AFS_DEBUG_CURSOR
bool "AFS server cursor debugging"
depends on AFS_FS
help
Say Y here to cause the contents of a server cursor to be dumped to
the dmesg log if the server rotation algorithm fails to successfully
contact a server.
See <file:Documentation/filesystems/afs.txt> for more information.
If unsure, say N.
......@@ -17,6 +17,7 @@ kafs-y := \
file.o \
flock.o \
fsclient.o \
fs_probe.o \
inode.o \
main.o \
misc.o \
......@@ -29,9 +30,13 @@ kafs-y := \
super.o \
netdevices.o \
vlclient.o \
vl_list.o \
vl_probe.o \
vl_rotate.o \
volume.o \
write.o \
xattr.o
xattr.o \
yfsclient.o
kafs-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_AFS_FS) := kafs.o
......@@ -64,19 +64,25 @@ struct afs_addr_list *afs_alloc_addrlist(unsigned int nr,
/*
* Parse a text string consisting of delimited addresses.
*/
struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
char delim,
unsigned short service,
unsigned short port)
struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *net,
const char *text, size_t len,
char delim,
unsigned short service,
unsigned short port)
{
struct afs_vlserver_list *vllist;
struct afs_addr_list *alist;
const char *p, *end = text + len;
const char *problem;
unsigned int nr = 0;
int ret = -ENOMEM;
_enter("%*.*s,%c", (int)len, (int)len, text, delim);
if (!len)
if (!len) {
_leave(" = -EDESTADDRREQ [empty]");
return ERR_PTR(-EDESTADDRREQ);
}
if (delim == ':' && (memchr(text, ',', len) || !memchr(text, '.', len)))
delim = ',';
......@@ -84,18 +90,24 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
/* Count the addresses */
p = text;
do {
if (!*p)
return ERR_PTR(-EINVAL);
if (!*p) {
problem = "nul";
goto inval;
}
if (*p == delim)
continue;
nr++;
if (*p == '[') {
p++;
if (p == end)
return ERR_PTR(-EINVAL);
if (p == end) {
problem = "brace1";
goto inval;
}
p = memchr(p, ']', end - p);
if (!p)
return ERR_PTR(-EINVAL);
if (!p) {
problem = "brace2";
goto inval;
}
p++;
if (p >= end)
break;
......@@ -109,10 +121,19 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
_debug("%u/%u addresses", nr, AFS_MAX_ADDRESSES);
alist = afs_alloc_addrlist(nr, service, port);
if (!alist)
vllist = afs_alloc_vlserver_list(1);
if (!vllist)
return ERR_PTR(-ENOMEM);
vllist->nr_servers = 1;
vllist->servers[0].server = afs_alloc_vlserver("<dummy>", 7, AFS_VL_PORT);
if (!vllist->servers[0].server)
goto error_vl;
alist = afs_alloc_addrlist(nr, service, AFS_VL_PORT);
if (!alist)
goto error;
/* Extract the addresses */
p = text;
do {
......@@ -135,17 +156,21 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
break;
}
if (in4_pton(p, q - p, (u8 *)&x[0], -1, &stop))
if (in4_pton(p, q - p, (u8 *)&x[0], -1, &stop)) {
family = AF_INET;
else if (in6_pton(p, q - p, (u8 *)x, -1, &stop))
} else if (in6_pton(p, q - p, (u8 *)x, -1, &stop)) {
family = AF_INET6;
else
} else {
problem = "family";
goto bad_address;
}
if (stop != q)
p = q;
if (stop != p) {
problem = "nostop";
goto bad_address;
}
p = q;
if (q < end && *q == ']')
p++;
......@@ -154,18 +179,23 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
/* Port number specification "+1234" */
xport = 0;
p++;
if (p >= end || !isdigit(*p))
if (p >= end || !isdigit(*p)) {
problem = "port";
goto bad_address;
}
do {
xport *= 10;
xport += *p - '0';
if (xport > 65535)
if (xport > 65535) {
problem = "pval";
goto bad_address;
}
p++;
} while (p < end && isdigit(*p));
} else if (*p == delim) {
p++;
} else {
problem = "weird";
goto bad_address;
}
}
......@@ -177,12 +207,23 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
} while (p < end);
rcu_assign_pointer(vllist->servers[0].server->addresses, alist);
_leave(" = [nr %u]", alist->nr_addrs);
return alist;
return vllist;
bad_address:
kfree(alist);
inval:
_leave(" = -EINVAL [%s %zu %*.*s]",
problem, p - text, (int)len, (int)len, text);
return ERR_PTR(-EINVAL);
bad_address:
_leave(" = -EINVAL [%s %zu %*.*s]",
problem, p - text, (int)len, (int)len, text);
ret = -EINVAL;
error:
afs_put_addrlist(alist);
error_vl:
afs_put_vlserverlist(net, vllist);
return ERR_PTR(ret);
}
/*
......@@ -201,30 +242,34 @@ static int afs_cmp_addr_list(const struct afs_addr_list *a1,
/*
* Perform a DNS query for VL servers and build a up an address list.
*/
struct afs_addr_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry)
struct afs_vlserver_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry)
{
struct afs_addr_list *alist;
char *vllist = NULL;
struct afs_vlserver_list *vllist;
char *result = NULL;
int ret;
_enter("%s", cell->name);
ret = dns_query("afsdb", cell->name, cell->name_len,
"", &vllist, _expiry);
if (ret < 0)
ret = dns_query("afsdb", cell->name, cell->name_len, "srv=1",
&result, _expiry);
if (ret < 0) {
_leave(" = %d [dns]", ret);
return ERR_PTR(ret);
alist = afs_parse_text_addrs(vllist, strlen(vllist), ',',
VL_SERVICE, AFS_VL_PORT);
if (IS_ERR(alist)) {
kfree(vllist);
if (alist != ERR_PTR(-ENOMEM))
pr_err("Failed to parse DNS data\n");
return alist;
}
kfree(vllist);
return alist;
if (*_expiry == 0)
*_expiry = ktime_get_real_seconds() + 60;
if (ret > 1 && result[0] == 0)
vllist = afs_extract_vlserver_list(cell, result, ret);
else
vllist = afs_parse_text_addrs(cell->net, result, ret, ',',
VL_SERVICE, AFS_VL_PORT);
kfree(result);
if (IS_ERR(vllist) && vllist != ERR_PTR(-ENOMEM))
pr_err("Failed to parse DNS data %ld\n", PTR_ERR(vllist));
return vllist;
}
/*
......@@ -258,6 +303,8 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port)
sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
srx = &alist->addrs[i];
srx->srx_family = AF_RXRPC;
srx->transport_type = SOCK_DGRAM;
srx->transport_len = sizeof(srx->transport.sin);
srx->transport.sin.sin_family = AF_INET;
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)
sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
srx = &alist->addrs[i];
srx->srx_family = AF_RXRPC;
srx->transport_type = SOCK_DGRAM;
srx->transport_len = sizeof(srx->transport.sin6);
srx->transport.sin6.sin6_family = AF_INET6;
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)
*/
bool afs_iterate_addresses(struct afs_addr_cursor *ac)
{
_enter("%hu+%hd", ac->start, (short)ac->index);
unsigned long set, failed;
int index;
if (!ac->alist)
return false;
if (ac->begun) {
ac->index++;
if (ac->index == ac->alist->nr_addrs)
ac->index = 0;
set = ac->alist->responded;
failed = ac->alist->failed;
_enter("%lx-%lx-%lx,%d", set, failed, ac->tried, ac->index);
if (ac->index == ac->start) {
ac->error = -EDESTADDRREQ;
return false;
}
}
ac->nr_iterations++;
set &= ~(failed | ac->tried);
if (!set)
return false;
ac->begun = true;
index = READ_ONCE(ac->alist->preferred);
if (test_bit(index, &set))
goto selected;
index = __ffs(set);
selected:
ac->index = index;
set_bit(index, &ac->tried);
ac->responded = false;
ac->addr = &ac->alist->addrs[ac->index];
return true;
}
......@@ -339,53 +396,13 @@ int afs_end_cursor(struct afs_addr_cursor *ac)
alist = ac->alist;
if (alist) {
if (ac->responded && ac->index != ac->start)
WRITE_ONCE(alist->index, ac->index);
if (ac->responded &&
ac->index != alist->preferred &&
test_bit(ac->alist->preferred, &ac->tried))
WRITE_ONCE(alist->preferred, ac->index);
afs_put_addrlist(alist);
ac->alist = NULL;
}
ac->addr = NULL;
ac->alist = NULL;
ac->begun = false;
return ac->error;
}
/*
* Set the address cursor for iterating over VL servers.
*/
int afs_set_vl_cursor(struct afs_addr_cursor *ac, struct afs_cell *cell)
{
struct afs_addr_list *alist;
int ret;
if (!rcu_access_pointer(cell->vl_addrs)) {
ret = wait_on_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET,
TASK_INTERRUPTIBLE);
if (ret < 0)
return ret;
if (!rcu_access_pointer(cell->vl_addrs) &&
ktime_get_real_seconds() < cell->dns_expiry)
return cell->error;
}
read_lock(&cell->vl_addrs_lock);
alist = rcu_dereference_protected(cell->vl_addrs,
lockdep_is_held(&cell->vl_addrs_lock));
if (alist->nr_addrs > 0)
afs_get_addrlist(alist);
else
alist = NULL;
read_unlock(&cell->vl_addrs_lock);
if (!alist)
return -EDESTADDRREQ;
ac->alist = alist;
ac->addr = NULL;
ac->start = READ_ONCE(alist->index);
ac->index = ac->start;
ac->error = 0;
ac->begun = false;
return 0;
}
......@@ -23,9 +23,9 @@
#define AFSPATHMAX 1024 /* Maximum length of a pathname plus NUL */
#define AFSOPAQUEMAX 1024 /* Maximum length of an opaque field */
typedef unsigned afs_volid_t;
typedef unsigned afs_vnodeid_t;
typedef unsigned long long afs_dataversion_t;
typedef u64 afs_volid_t;
typedef u64 afs_vnodeid_t;
typedef u64 afs_dataversion_t;
typedef enum {
AFSVL_RWVOL, /* read/write volume */
......@@ -52,8 +52,9 @@ typedef enum {
*/
struct afs_fid {
afs_volid_t vid; /* volume ID */
afs_vnodeid_t vnode; /* file index within volume */
unsigned unique; /* unique ID number (file index version) */
afs_vnodeid_t vnode; /* Lower 64-bits of file index within volume */
u32 vnode_hi; /* Upper 32-bits of file index */
u32 unique; /* unique ID number (file index version) */
};
/*
......@@ -67,14 +68,14 @@ typedef enum {
} afs_callback_type_t;
struct afs_callback {
time64_t expires_at; /* Time at which expires */
unsigned version; /* Callback version */
unsigned expiry; /* Time at which expires */
afs_callback_type_t type; /* Type of callback */
};
struct afs_callback_break {
struct afs_fid fid; /* File identifier */
struct afs_callback cb; /* Callback details */
//struct afs_callback cb; /* Callback details */
};
#define AFSCBMAX 50 /* maximum callbacks transferred per bulk op */
......@@ -129,19 +130,18 @@ typedef u32 afs_access_t;
struct afs_file_status {
u64 size; /* file size */
afs_dataversion_t data_version; /* current data version */
time_t mtime_client; /* last time client changed data */
time_t mtime_server; /* last time server changed data */
unsigned abort_code; /* Abort if bulk-fetching this failed */
afs_file_type_t type; /* file type */
unsigned nlink; /* link count */
u32 author; /* author ID */
u32 owner; /* owner ID */
u32 group; /* group ID */
struct timespec64 mtime_client; /* Last time client changed data */
struct timespec64 mtime_server; /* Last time server changed data */
s64 author; /* author ID */
s64 owner; /* owner ID */
s64 group; /* group ID */
afs_access_t caller_access; /* access rights for authenticated caller */
afs_access_t anon_access; /* access rights for unauthenticated caller */
umode_t mode; /* UNIX mode */
afs_file_type_t type; /* file type */
u32 nlink; /* link count */
s32 lock_count; /* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */
u32 abort_code; /* Abort if bulk-fetching this failed */
};
/*
......@@ -158,25 +158,27 @@ struct afs_file_status {
* AFS volume synchronisation information
*/
struct afs_volsync {
time_t creation; /* volume creation time */
time64_t creation; /* volume creation time */
};
/*
* AFS volume status record
*/
struct afs_volume_status {
u32 vid; /* volume ID */
u32 parent_id; /* parent volume ID */
afs_volid_t vid; /* volume ID */
afs_volid_t parent_id; /* parent volume ID */
u8 online; /* true if volume currently online and available */
u8 in_service; /* true if volume currently in service */
u8 blessed; /* same as in_service */
u8 needs_salvage; /* true if consistency checking required */
u32 type; /* volume type (afs_voltype_t) */
u32 min_quota; /* minimum space set aside (blocks) */
u32 max_quota; /* maximum space this volume may occupy (blocks) */
u32 blocks_in_use; /* space this volume currently occupies (blocks) */
u32 part_blocks_avail; /* space available in volume's partition */
u32 part_max_blocks; /* size of volume's partition */
u64 min_quota; /* minimum space set aside (blocks) */
u64 max_quota; /* maximum space this volume may occupy (blocks) */
u64 blocks_in_use; /* space this volume currently occupies (blocks) */
u64 part_blocks_avail; /* space available in volume's partition */
u64 part_max_blocks; /* size of volume's partition */
s64 vol_copy_date;
s64 vol_backup_date;
};
#define AFS_BLOCK_SIZE 1024
......
......@@ -49,7 +49,7 @@ static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
struct afs_vnode *vnode = cookie_netfs_data;
struct afs_vnode_cache_aux aux;
_enter("{%x,%x,%llx},%p,%u",
_enter("{%llx,%x,%llx},%p,%u",
vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
buffer, buflen);
......
......@@ -210,12 +210,10 @@ void afs_init_callback_state(struct afs_server *server)
/*
* actually break a callback
*/
void afs_break_callback(struct afs_vnode *vnode)
void __afs_break_callback(struct afs_vnode *vnode)
{
_enter("");
write_seqlock(&vnode->cb_lock);
clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
vnode->cb_break++;
......@@ -230,7 +228,12 @@ void afs_break_callback(struct afs_vnode *vnode)
afs_lock_may_be_available(vnode);
spin_unlock(&vnode->lock);
}
}
void afs_break_callback(struct afs_vnode *vnode)
{
write_seqlock(&vnode->cb_lock);
__afs_break_callback(vnode);
write_sequnlock(&vnode->cb_lock);
}
......@@ -310,14 +313,10 @@ void afs_break_callbacks(struct afs_server *server, size_t count,
/* TODO: Sort the callback break list by volume ID */
for (; count > 0; callbacks++, count--) {
_debug("- Fid { vl=%08x n=%u u=%u } CB { v=%u x=%u t=%u }",
_debug("- Fid { vl=%08llx n=%llu u=%u }",
callbacks->fid.vid,
callbacks->fid.vnode,
callbacks->fid.unique,
callbacks->cb.version,
callbacks->cb.expiry,
callbacks->cb.type
);
callbacks->fid.unique);
afs_break_one_callback(server, &callbacks->fid);
}
......
......@@ -20,6 +20,8 @@
#include "internal.h"
static unsigned __read_mostly afs_cell_gc_delay = 10;
static unsigned __read_mostly afs_cell_min_ttl = 10 * 60;
static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60;
static void afs_manage_cell(struct work_struct *);
......@@ -119,7 +121,7 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
*/
static struct afs_cell *afs_alloc_cell(struct afs_net *net,
const char *name, unsigned int namelen,
const char *vllist)
const char *addresses)
{
struct afs_cell *cell;
int i, ret;
......@@ -134,7 +136,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
if (namelen == 5 && memcmp(name, "@cell", 5) == 0)
return ERR_PTR(-EINVAL);
_enter("%*.*s,%s", namelen, namelen, name, vllist);
_enter("%*.*s,%s", namelen, namelen, name, addresses);
cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL);
if (!cell) {
......@@ -153,23 +155,26 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
(1 << AFS_CELL_FL_NO_LOOKUP_YET));
INIT_LIST_HEAD(&cell->proc_volumes);
rwlock_init(&cell->proc_lock);
rwlock_init(&cell->vl_addrs_lock);
rwlock_init(&cell->vl_servers_lock);
/* Fill in the VL server list if we were given a list of addresses to
* use.
*/
if (vllist) {
struct afs_addr_list *alist;
alist = afs_parse_text_addrs(vllist, strlen(vllist), ':',
VL_SERVICE, AFS_VL_PORT);
if (IS_ERR(alist)) {
ret = PTR_ERR(alist);
if (addresses) {
struct afs_vlserver_list *vllist;
vllist = afs_parse_text_addrs(net,
addresses, strlen(addresses), ':',
VL_SERVICE, AFS_VL_PORT);
if (IS_ERR(vllist)) {
ret = PTR_ERR(vllist);
goto parse_failed;
}
rcu_assign_pointer(cell->vl_addrs, alist);
rcu_assign_pointer(cell->vl_servers, vllist);
cell->dns_expiry = TIME64_MAX;
} else {
cell->dns_expiry = ktime_get_real_seconds();
}
_leave(" = %p", cell);
......@@ -356,26 +361,40 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
*/
static void afs_update_cell(struct afs_cell *cell)
{
struct afs_addr_list *alist, *old;
time64_t now, expiry;
struct afs_vlserver_list *vllist, *old;
unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl);
unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl);
time64_t now, expiry = 0;
_enter("%s", cell->name);
alist = afs_dns_query(cell, &expiry);
if (IS_ERR(alist)) {
switch (PTR_ERR(alist)) {
vllist = afs_dns_query(cell, &expiry);
now = ktime_get_real_seconds();
if (min_ttl > max_ttl)
max_ttl = min_ttl;
if (expiry < now + min_ttl)
expiry = now + min_ttl;
else if (expiry > now + max_ttl)
expiry = now + max_ttl;
if (IS_ERR(vllist)) {
switch (PTR_ERR(vllist)) {
case -ENODATA:
/* The DNS said that the cell does not exist */
case -EDESTADDRREQ:
/* The DNS said that the cell does not exist or there
* weren't any addresses to be had.
*/
set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
cell->dns_expiry = ktime_get_real_seconds() + 61;
cell->dns_expiry = expiry;
break;
case -EAGAIN:
case -ECONNREFUSED:
default:
set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
cell->dns_expiry = ktime_get_real_seconds() + 10;
cell->dns_expiry = now + 10;
break;
}
......@@ -387,12 +406,12 @@ static void afs_update_cell(struct afs_cell *cell)
/* Exclusion on changing vl_addrs is achieved by a
* non-reentrant work item.
*/
old = rcu_dereference_protected(cell->vl_addrs, true);
rcu_assign_pointer(cell->vl_addrs, alist);
old = rcu_dereference_protected(cell->vl_servers, true);
rcu_assign_pointer(cell->vl_servers, vllist);
cell->dns_expiry = expiry;
if (old)
afs_put_addrlist(old);
afs_put_vlserverlist(cell->net, old);
}
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)
ASSERTCMP(atomic_read(&cell->usage), ==, 0);
afs_put_addrlist(rcu_access_pointer(cell->vl_addrs));
afs_put_vlserverlist(cell->net, rcu_access_pointer(cell->vl_servers));
key_put(cell->anonymous_key);
kfree(cell);
......
......@@ -16,6 +16,7 @@
#include <linux/ip.h>
#include "internal.h"
#include "afs_cm.h"
#include "protocol_yfs.h"
static int afs_deliver_cb_init_call_back_state(struct afs_call *);
static int afs_deliver_cb_init_call_back_state3(struct afs_call *);
......@@ -30,6 +31,8 @@ static void SRXAFSCB_Probe(struct work_struct *);
static void SRXAFSCB_ProbeUuid(struct work_struct *);
static void SRXAFSCB_TellMeAboutYourself(struct work_struct *);
static int afs_deliver_yfs_cb_callback(struct afs_call *);
#define CM_NAME(name) \
const char afs_SRXCB##name##_name[] __tracepoint_string = \
"CB." #name
......@@ -100,13 +103,26 @@ static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
.work = SRXAFSCB_TellMeAboutYourself,
};
/*
* YFS CB.CallBack operation type
*/
static CM_NAME(YFS_CallBack);
static const struct afs_call_type afs_SRXYFSCB_CallBack = {
.name = afs_SRXCBYFS_CallBack_name,
.deliver = afs_deliver_yfs_cb_callback,
.destructor = afs_cm_destructor,
.work = SRXAFSCB_CallBack,
};
/*
* route an incoming cache manager call
* - return T if supported, F if not
*/
bool afs_cm_incoming_call(struct afs_call *call)
{
_enter("{CB.OP %u}", call->operation_ID);
_enter("{%u, CB.OP %u}", call->service_id, call->operation_ID);
call->epoch = rxrpc_kernel_get_epoch(call->net->socket, call->rxcall);
switch (call->operation_ID) {
case CBCallBack:
......@@ -127,11 +143,101 @@ bool afs_cm_incoming_call(struct afs_call *call)
case CBTellMeAboutYourself:
call->type = &afs_SRXCBTellMeAboutYourself;
return true;
case YFSCBCallBack:
if (call->service_id != YFS_CM_SERVICE)
return false;
call->type = &afs_SRXYFSCB_CallBack;
return true;
default:
return false;
}
}
/*
* Record a probe to the cache manager from a server.
*/
static int afs_record_cm_probe(struct afs_call *call, struct afs_server *server)
{
_enter("");
if (test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags) &&
!test_bit(AFS_SERVER_FL_PROBING, &server->flags)) {
if (server->cm_epoch == call->epoch)
return 0;
if (!server->probe.said_rebooted) {
pr_notice("kAFS: FS rebooted %pU\n", &server->uuid);
server->probe.said_rebooted = true;
}
}
spin_lock(&server->probe_lock);
if (!test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags)) {
server->cm_epoch = call->epoch;
server->probe.cm_epoch = call->epoch;
goto out;
}
if (server->probe.cm_probed &&
call->epoch != server->probe.cm_epoch &&
!server->probe.said_inconsistent) {
pr_notice("kAFS: FS endpoints inconsistent %pU\n",
&server->uuid);
server->probe.said_inconsistent = true;
}
if (!server->probe.cm_probed || call->epoch == server->cm_epoch)
server->probe.cm_epoch = server->cm_epoch;
out:
server->probe.cm_probed = true;
spin_unlock(&server->probe_lock);
return 0;
}
/*
* Find the server record by peer address and record a probe to the cache
* manager from a server.
*/
static int afs_find_cm_server_by_peer(struct afs_call *call)
{
struct sockaddr_rxrpc srx;
struct afs_server *server;
rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
server = afs_find_server(call->net, &srx);
if (!server) {
trace_afs_cm_no_server(call, &srx);
return 0;
}
call->cm_server = server;
return afs_record_cm_probe(call, server);
}
/*
* Find the server record by server UUID and record a probe to the cache
* manager from a server.
*/
static int afs_find_cm_server_by_uuid(struct afs_call *call,
struct afs_uuid *uuid)
{
struct afs_server *server;
rcu_read_lock();
server = afs_find_server_by_uuid(call->net, call->request);
rcu_read_unlock();
if (!server) {
trace_afs_cm_no_server_u(call, call->request);
return 0;
}
call->cm_server = server;
return afs_record_cm_probe(call, server);
}
/*
* Clean up a cache manager call.
*/
......@@ -168,7 +274,6 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
static int afs_deliver_cb_callback(struct afs_call *call)
{
struct afs_callback_break *cb;
struct sockaddr_rxrpc srx;
__be32 *bp;
int ret, loop;
......@@ -176,32 +281,32 @@ static int afs_deliver_cb_callback(struct afs_call *call)
switch (call->unmarshall) {
case 0:
call->offset = 0;
afs_extract_to_tmp(call);
call->unmarshall++;
/* extract the FID array and its count in two steps */
case 1:
_debug("extract FID count");
ret = afs_extract_data(call, &call->tmp, 4, true);
ret = afs_extract_data(call, true);
if (ret < 0)
return ret;
call->count = ntohl(call->tmp);
_debug("FID count: %u", call->count);
if (call->count > AFSCBMAX)
return afs_protocol_error(call, -EBADMSG);
return afs_protocol_error(call, -EBADMSG,
afs_eproto_cb_fid_count);
call->buffer = kmalloc(array3_size(call->count, 3, 4),
GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
call->offset = 0;
afs_extract_to_buf(call, call->count * 3 * 4);
call->unmarshall++;
case 2:
_debug("extract FID array");
ret = afs_extract_data(call, call->buffer,
call->count * 3 * 4, true);
ret = afs_extract_data(call, true);
if (ret < 0)
return ret;
......@@ -218,59 +323,46 @@ static int afs_deliver_cb_callback(struct afs_call *call)
cb->fid.vid = ntohl(*bp++);
cb->fid.vnode = ntohl(*bp++);
cb->fid.unique = ntohl(*bp++);
cb->cb.type = AFSCM_CB_UNTYPED;
}
call->offset = 0;
afs_extract_to_tmp(call);
call->unmarshall++;
/* extract the callback array and its count in two steps */
case 3:
_debug("extract CB count");
ret = afs_extract_data(call, &call->tmp, 4, true);
ret = afs_extract_data(call, true);
if (ret < 0)
return ret;
call->count2 = ntohl(call->tmp);
_debug("CB count: %u", call->count2);
if (call->count2 != call->count && call->count2 != 0)
return afs_protocol_error(call, -EBADMSG);
call->offset = 0;
return afs_protocol_error(call, -EBADMSG,
afs_eproto_cb_count);
call->_iter = &call->iter;
iov_iter_discard(&call->iter, READ, call->count2 * 3 * 4);
call->unmarshall++;
case 4:
_debug("extract CB array");
ret = afs_extract_data(call, call->buffer,
call->count2 * 3 * 4, false);
_debug("extract discard %zu/%u",
iov_iter_count(&call->iter), call->count2 * 3 * 4);
ret = afs_extract_data(call, false);
if (ret < 0)
return ret;
_debug("unmarshall CB array");
cb = call->request;
bp = call->buffer;
for (loop = call->count2; loop > 0; loop--, cb++) {
cb->cb.version = ntohl(*bp++);
cb->cb.expiry = ntohl(*bp++);
cb->cb.type = ntohl(*bp++);
}
call->offset = 0;
call->unmarshall++;
case 5:
break;
}
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return -EIO;
return afs_io_error(call, afs_io_error_cm_reply);
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
call->cm_server = afs_find_server(call->net, &srx);
if (!call->cm_server)
trace_afs_cm_no_server(call, &srx);
return afs_queue_call_work(call);
return afs_find_cm_server_by_peer(call);
}
/*
......@@ -294,24 +386,18 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
*/
static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
{
struct sockaddr_rxrpc srx;
int ret;
_enter("");
rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
ret = afs_extract_data(call, NULL, 0, false);
afs_extract_discard(call, 0);
ret = afs_extract_data(call, false);
if (ret < 0)
return ret;
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
call->cm_server = afs_find_server(call->net, &srx);
if (!call->cm_server)
trace_afs_cm_no_server(call, &srx);
return afs_queue_call_work(call);
return afs_find_cm_server_by_peer(call);
}
/*
......@@ -330,16 +416,15 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
switch (call->unmarshall) {
case 0:
call->offset = 0;
call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
afs_extract_to_buf(call, 11 * sizeof(__be32));
call->unmarshall++;
case 1:
_debug("extract UUID");
ret = afs_extract_data(call, call->buffer,
11 * sizeof(__be32), false);
ret = afs_extract_data(call, false);
switch (ret) {
case 0: break;
case -EAGAIN: return 0;
......@@ -362,7 +447,6 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
for (loop = 0; loop < 6; loop++)
r->node[loop] = ntohl(b[loop + 5]);
call->offset = 0;
call->unmarshall++;
case 2:
......@@ -370,17 +454,11 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
}
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return -EIO;
return afs_io_error(call, afs_io_error_cm_reply);
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
rcu_read_lock();
call->cm_server = afs_find_server_by_uuid(call->net, call->request);
rcu_read_unlock();
if (!call->cm_server)
trace_afs_cm_no_server_u(call, call->request);
return afs_queue_call_work(call);
return afs_find_cm_server_by_uuid(call, call->request);
}
/*
......@@ -405,14 +483,14 @@ static int afs_deliver_cb_probe(struct afs_call *call)
_enter("");
ret = afs_extract_data(call, NULL, 0, false);
afs_extract_discard(call, 0);
ret = afs_extract_data(call, false);
if (ret < 0)
return ret;
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return -EIO;
return afs_queue_call_work(call);
return afs_io_error(call, afs_io_error_cm_reply);
return afs_find_cm_server_by_peer(call);
}
/*
......@@ -453,16 +531,15 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
switch (call->unmarshall) {
case 0:
call->offset = 0;
call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
afs_extract_to_buf(call, 11 * sizeof(__be32));
call->unmarshall++;
case 1:
_debug("extract UUID");
ret = afs_extract_data(call, call->buffer,
11 * sizeof(__be32), false);
ret = afs_extract_data(call, false);
switch (ret) {
case 0: break;
case -EAGAIN: return 0;
......@@ -485,7 +562,6 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
for (loop = 0; loop < 6; loop++)
r->node[loop] = ntohl(b[loop + 5]);
call->offset = 0;
call->unmarshall++;
case 2:
......@@ -493,9 +569,8 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
}
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return -EIO;
return afs_queue_call_work(call);
return afs_io_error(call, afs_io_error_cm_reply);
return afs_find_cm_server_by_uuid(call, call->request);
}
/*
......@@ -570,12 +645,88 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
_enter("");
ret = afs_extract_data(call, NULL, 0, false);
afs_extract_discard(call, 0);
ret = afs_extract_data(call, false);
if (ret < 0)
return ret;
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return -EIO;
return afs_io_error(call, afs_io_error_cm_reply);
return afs_find_cm_server_by_peer(call);
}
/*
* deliver request data to a YFS CB.CallBack call
*/
static int afs_deliver_yfs_cb_callback(struct afs_call *call)
{
struct afs_callback_break *cb;
struct yfs_xdr_YFSFid *bp;
size_t size;
int ret, loop;
_enter("{%u}", call->unmarshall);
switch (call->unmarshall) {
case 0:
afs_extract_to_tmp(call);
call->unmarshall++;
/* extract the FID array and its count in two steps */
case 1:
_debug("extract FID count");
ret = afs_extract_data(call, true);
if (ret < 0)
return ret;
call->count = ntohl(call->tmp);
_debug("FID count: %u", call->count);
if (call->count > YFSCBMAX)
return afs_protocol_error(call, -EBADMSG,
afs_eproto_cb_fid_count);
size = array_size(call->count, sizeof(struct yfs_xdr_YFSFid));
call->buffer = kmalloc(size, GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
afs_extract_to_buf(call, size);
call->unmarshall++;
case 2:
_debug("extract FID array");
ret = afs_extract_data(call, false);
if (ret < 0)
return ret;
_debug("unmarshall FID array");
call->request = kcalloc(call->count,
sizeof(struct afs_callback_break),
GFP_KERNEL);
if (!call->request)
return -ENOMEM;
cb = call->request;
bp = call->buffer;
for (loop = call->count; loop > 0; loop--, cb++) {
cb->fid.vid = xdr_to_u64(bp->volume);
cb->fid.vnode = xdr_to_u64(bp->vnode.lo);
cb->fid.vnode_hi = ntohl(bp->vnode.hi);
cb->fid.unique = ntohl(bp->vnode.unique);
bp++;
}
afs_extract_to_tmp(call);
call->unmarshall++;
case 3:
break;
}
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return afs_io_error(call, afs_io_error_cm_reply);
return afs_queue_call_work(call);
/* We'll need the file server record as that tells us which set of
* vnodes to operate upon.
*/
return afs_find_cm_server_by_peer(call);
}
......@@ -138,6 +138,7 @@ static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page,
ntohs(dbuf->blocks[tmp].hdr.magic));
trace_afs_dir_check_failed(dvnode, off, i_size);
kunmap(page);
trace_afs_file_error(dvnode, -EIO, afs_file_error_dir_bad_magic);
goto error;
}
......@@ -190,9 +191,11 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
retry:
i_size = i_size_read(&dvnode->vfs_inode);
if (i_size < 2048)
return ERR_PTR(-EIO);
if (i_size > 2048 * 1024)
return ERR_PTR(afs_bad(dvnode, afs_file_error_dir_small));
if (i_size > 2048 * 1024) {
trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
return ERR_PTR(-EFBIG);
}
_enter("%llu", i_size);
......@@ -315,7 +318,8 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
/*
* deal with one block in an AFS directory
*/
static int afs_dir_iterate_block(struct dir_context *ctx,
static int afs_dir_iterate_block(struct afs_vnode *dvnode,
struct dir_context *ctx,
union afs_xdr_dir_block *block,
unsigned blkoff)
{
......@@ -365,7 +369,7 @@ static int afs_dir_iterate_block(struct dir_context *ctx,
" (len %u/%zu)",
blkoff / sizeof(union afs_xdr_dir_block),
offset, next, tmp, nlen);
return -EIO;
return afs_bad(dvnode, afs_file_error_dir_over_end);
}
if (!(block->hdr.bitmap[next / 8] &
(1 << (next % 8)))) {
......@@ -373,7 +377,7 @@ static int afs_dir_iterate_block(struct dir_context *ctx,
" %u unmarked extension (len %u/%zu)",
blkoff / sizeof(union afs_xdr_dir_block),
offset, next, tmp, nlen);
return -EIO;
return afs_bad(dvnode, afs_file_error_dir_unmarked_ext);
}
_debug("ENT[%zu.%u]: ext %u/%zu",
......@@ -442,7 +446,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
*/
page = req->pages[blkoff / PAGE_SIZE];
if (!page) {
ret = -EIO;
ret = afs_bad(dvnode, afs_file_error_dir_missing_page);
break;
}
mark_page_accessed(page);
......@@ -455,7 +459,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
do {
dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
sizeof(union afs_xdr_dir_block)];
ret = afs_dir_iterate_block(ctx, dblock, blkoff);
ret = afs_dir_iterate_block(dvnode, ctx, dblock, blkoff);
if (ret != 1) {
kunmap(page);
goto out;
......@@ -548,7 +552,7 @@ static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
}
*fid = cookie.fid;
_leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique);
_leave(" = 0 { vn=%llu u=%u }", fid->vnode, fid->unique);
return 0;
}
......@@ -826,7 +830,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
struct key *key;
int ret;
_enter("{%x:%u},%p{%pd},",
_enter("{%llx:%llu},%p{%pd},",
dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry);
ASSERTCMP(d_inode(dentry), ==, NULL);
......@@ -896,7 +900,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
if (d_really_is_positive(dentry)) {
vnode = AFS_FS_I(d_inode(dentry));
_enter("{v={%x:%u} n=%pd fl=%lx},",
_enter("{v={%llx:%llu} n=%pd fl=%lx},",
vnode->fid.vid, vnode->fid.vnode, dentry,
vnode->flags);
} else {
......@@ -965,7 +969,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
/* if the vnode ID has changed, then the dirent points to a
* different file */
if (fid.vnode != vnode->fid.vnode) {
_debug("%pd: dirent changed [%u != %u]",
_debug("%pd: dirent changed [%llu != %llu]",
dentry, fid.vnode,
vnode->fid.vnode);
goto not_found;
......@@ -1085,6 +1089,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
vnode = AFS_FS_I(inode);
set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
afs_vnode_commit_status(fc, vnode, 0);
d_add(new_dentry, inode);
}
......@@ -1104,7 +1109,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
mode |= S_IFDIR;
_enter("{%x:%u},{%pd},%ho",
_enter("{%llx:%llu},{%pd},%ho",
dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
key = afs_request_key(dvnode->volume->cell);
......@@ -1169,12 +1174,12 @@ static void afs_dir_remove_subdir(struct dentry *dentry)
static int afs_rmdir(struct inode *dir, struct dentry *dentry)
{
struct afs_fs_cursor fc;
struct afs_vnode *dvnode = AFS_FS_I(dir);
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
struct key *key;
u64 data_version = dvnode->status.data_version;
int ret;
_enter("{%x:%u},{%pd}",
_enter("{%llx:%llu},{%pd}",
dvnode->fid.vid, dvnode->fid.vnode, dentry);
key = afs_request_key(dvnode->volume->cell);
......@@ -1183,11 +1188,19 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
goto error;
}
/* Try to make sure we have a callback promise on the victim. */
if (d_really_is_positive(dentry)) {
vnode = AFS_FS_I(d_inode(dentry));
ret = afs_validate(vnode, key);
if (ret < 0)
goto error_key;
}
ret = -ERESTARTSYS;
if (afs_begin_vnode_operation(&fc, dvnode, key)) {
while (afs_select_fileserver(&fc)) {
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
afs_fs_remove(&fc, dentry->d_name.name, true,
afs_fs_remove(&fc, vnode, dentry->d_name.name, true,
data_version);
}
......@@ -1201,6 +1214,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
}
}
error_key:
key_put(key);
error:
return ret;
......@@ -1231,7 +1245,9 @@ static int afs_dir_remove_link(struct dentry *dentry, struct key *key,
if (d_really_is_positive(dentry)) {
struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
if (dir_valid) {
if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
/* Already done */
} else if (dir_valid) {
drop_nlink(&vnode->vfs_inode);
if (vnode->vfs_inode.i_nlink == 0) {
set_bit(AFS_VNODE_DELETED, &vnode->flags);
......@@ -1260,13 +1276,13 @@ static int afs_dir_remove_link(struct dentry *dentry, struct key *key,
static int afs_unlink(struct inode *dir, struct dentry *dentry)
{
struct afs_fs_cursor fc;
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
struct key *key;
unsigned long d_version = (unsigned long)dentry->d_fsdata;
u64 data_version = dvnode->status.data_version;
int ret;
_enter("{%x:%u},{%pd}",
_enter("{%llx:%llu},{%pd}",
dvnode->fid.vid, dvnode->fid.vnode, dentry);
if (dentry->d_name.len >= AFSNAMEMAX)
......@@ -1290,7 +1306,18 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
if (afs_begin_vnode_operation(&fc, dvnode, key)) {
while (afs_select_fileserver(&fc)) {
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
afs_fs_remove(&fc, dentry->d_name.name, false,
if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) &&
!test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) {
yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name,
data_version);
if (fc.ac.error != -ECONNABORTED ||
fc.ac.abort_code != RXGEN_OPCODE)
continue;
set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags);
}
afs_fs_remove(&fc, vnode, dentry->d_name.name, false,
data_version);
}
......@@ -1330,7 +1357,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
mode |= S_IFREG;
_enter("{%x:%u},{%pd},%ho,",
_enter("{%llx:%llu},{%pd},%ho,",
dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
ret = -ENAMETOOLONG;
......@@ -1393,7 +1420,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
dvnode = AFS_FS_I(dir);
data_version = dvnode->status.data_version;
_enter("{%x:%u},{%x:%u},{%pd}",
_enter("{%llx:%llu},{%llx:%llu},{%pd}",
vnode->fid.vid, vnode->fid.vnode,
dvnode->fid.vid, dvnode->fid.vnode,
dentry);
......@@ -1464,7 +1491,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
u64 data_version = dvnode->status.data_version;
int ret;
_enter("{%x:%u},{%pd},%s",
_enter("{%llx:%llu},{%pd},%s",
dvnode->fid.vid, dvnode->fid.vnode, dentry,
content);
......@@ -1540,7 +1567,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
orig_data_version = orig_dvnode->status.data_version;
new_data_version = new_dvnode->status.data_version;
_enter("{%x:%u},{%x:%u},{%x:%u},{%pd}",
_enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}",
orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
vnode->fid.vid, vnode->fid.vnode,
new_dvnode->fid.vid, new_dvnode->fid.vnode,
......@@ -1607,7 +1634,7 @@ static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags)
{
struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
_enter("{{%x:%u}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
_enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
set_page_private(page, 0);
ClearPagePrivate(page);
......
......@@ -46,7 +46,7 @@ static int afs_probe_cell_name(struct dentry *dentry)
return 0;
}
ret = dns_query("afsdb", name, len, "", NULL, NULL);
ret = dns_query("afsdb", name, len, "srv=1", NULL, NULL);
if (ret == -ENODATA)
ret = -EDESTADDRREQ;
return ret;
......@@ -62,7 +62,7 @@ struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
struct inode *inode;
int ret = -ENOENT;
_enter("%p{%pd}, {%x:%u}",
_enter("%p{%pd}, {%llx:%llu}",
dentry, dentry, vnode->fid.vid, vnode->fid.vnode);
if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
......
......@@ -121,7 +121,7 @@ int afs_open(struct inode *inode, struct file *file)
struct key *key;
int ret;
_enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
_enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode);
key = afs_request_key(vnode->volume->cell);
if (IS_ERR(key)) {
......@@ -170,7 +170,7 @@ int afs_release(struct inode *inode, struct file *file)
struct afs_vnode *vnode = AFS_FS_I(inode);
struct afs_file *af = file->private_data;
_enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
_enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode);
if ((file->f_mode & FMODE_WRITE))
return vfs_fsync(file, 0);
......@@ -228,7 +228,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de
struct afs_fs_cursor fc;
int ret;
_enter("%s{%x:%u.%u},%x,,,",
_enter("%s{%llx:%llu.%u},%x,,,",
vnode->volume->name,
vnode->fid.vid,
vnode->fid.vnode,
......@@ -634,7 +634,7 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
unsigned long priv;
_enter("{{%x:%u}[%lu],%lx},%x",
_enter("{{%llx:%llu}[%lu],%lx},%x",
vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
gfp_flags);
......
......@@ -29,7 +29,7 @@ static const struct file_lock_operations afs_lock_ops = {
*/
void afs_lock_may_be_available(struct afs_vnode *vnode)
{
_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
_enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0);
}
......@@ -76,7 +76,7 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key,
struct afs_fs_cursor fc;
int ret;
_enter("%s{%x:%u.%u},%x,%u",
_enter("%s{%llx:%llu.%u},%x,%u",
vnode->volume->name,
vnode->fid.vid,
vnode->fid.vnode,
......@@ -107,7 +107,7 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key)
struct afs_fs_cursor fc;
int ret;
_enter("%s{%x:%u.%u},%x",
_enter("%s{%llx:%llu.%u},%x",
vnode->volume->name,
vnode->fid.vid,
vnode->fid.vnode,
......@@ -138,7 +138,7 @@ static int afs_release_lock(struct afs_vnode *vnode, struct key *key)
struct afs_fs_cursor fc;
int ret;
_enter("%s{%x:%u.%u},%x",
_enter("%s{%llx:%llu.%u},%x",
vnode->volume->name,
vnode->fid.vid,
vnode->fid.vnode,
......@@ -175,7 +175,7 @@ void afs_lock_work(struct work_struct *work)
struct key *key;
int ret;
_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
_enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
spin_lock(&vnode->lock);
......@@ -192,7 +192,7 @@ void afs_lock_work(struct work_struct *work)
ret = afs_release_lock(vnode, vnode->lock_key);
if (ret < 0)
printk(KERN_WARNING "AFS:"
" Failed to release lock on {%x:%x} error %d\n",
" Failed to release lock on {%llx:%llx} error %d\n",
vnode->fid.vid, vnode->fid.vnode, ret);
spin_lock(&vnode->lock);
......@@ -229,7 +229,7 @@ void afs_lock_work(struct work_struct *work)
key_put(key);
if (ret < 0)
pr_warning("AFS: Failed to extend lock on {%x:%x} error %d\n",
pr_warning("AFS: Failed to extend lock on {%llx:%llx} error %d\n",
vnode->fid.vid, vnode->fid.vnode, ret);
spin_lock(&vnode->lock);
......@@ -430,7 +430,7 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl)
struct key *key = afs_file_key(file);
int ret;
_enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
_enter("{%llx:%llu},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
/* only whole-file locks are supported */
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)
struct afs_vnode *vnode = AFS_FS_I(locks_inode(file));
int ret;
_enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
_enter("{%llx:%llu},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
/* Flush all pending writes before doing anything with locks. */
vfs_fsync(file, 0);
......@@ -639,7 +639,7 @@ int afs_lock(struct file *file, int cmd, struct file_lock *fl)
{
struct afs_vnode *vnode = AFS_FS_I(locks_inode(file));
_enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}",
_enter("{%llx:%llu},%d,{t=%x,fl=%x,r=%Ld:%Ld}",
vnode->fid.vid, vnode->fid.vnode, cmd,
fl->fl_type, fl->fl_flags,
(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)
{
struct afs_vnode *vnode = AFS_FS_I(locks_inode(file));
_enter("{%x:%u},%d,{t=%x,fl=%x}",
_enter("{%llx:%llu},%d,{t=%x,fl=%x}",
vnode->fid.vid, vnode->fid.vnode, cmd,
fl->fl_type, fl->fl_flags);
......
/* AFS fileserver probing
*
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include "afs_fs.h"
#include "internal.h"
#include "protocol_yfs.h"
static bool afs_fs_probe_done(struct afs_server *server)
{
if (!atomic_dec_and_test(&server->probe_outstanding))
return false;
wake_up_var(&server->probe_outstanding);
clear_bit_unlock(AFS_SERVER_FL_PROBING, &server->flags);
wake_up_bit(&server->flags, AFS_SERVER_FL_PROBING);
return true;
}
/*
* Process the result of probing a fileserver. This is called after successful
* or failed delivery of an FS.GetCapabilities operation.
*/
void afs_fileserver_probe_result(struct afs_call *call)
{
struct afs_addr_list *alist = call->alist;
struct afs_server *server = call->reply[0];
unsigned int server_index = (long)call->reply[1];
unsigned int index = call->addr_ix;
unsigned int rtt = UINT_MAX;
bool have_result = false;
u64 _rtt;
int ret = call->error;
_enter("%pU,%u", &server->uuid, index);
spin_lock(&server->probe_lock);
switch (ret) {
case 0:
server->probe.error = 0;
goto responded;
case -ECONNABORTED:
if (!server->probe.responded) {
server->probe.abort_code = call->abort_code;
server->probe.error = ret;
}
goto responded;
case -ENOMEM:
case -ENONET:
server->probe.local_failure = true;
afs_io_error(call, afs_io_error_fs_probe_fail);
goto out;
case -ECONNRESET: /* Responded, but call expired. */
case -ENETUNREACH:
case -EHOSTUNREACH:
case -ECONNREFUSED:
case -ETIMEDOUT:
case -ETIME:
default:
clear_bit(index, &alist->responded);
set_bit(index, &alist->failed);
if (!server->probe.responded &&
(server->probe.error == 0 ||
server->probe.error == -ETIMEDOUT ||
server->probe.error == -ETIME))
server->probe.error = ret;
afs_io_error(call, afs_io_error_fs_probe_fail);
goto out;
}
responded:
set_bit(index, &alist->responded);
clear_bit(index, &alist->failed);
if (call->service_id == YFS_FS_SERVICE) {
server->probe.is_yfs = true;
set_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
alist->addrs[index].srx_service = call->service_id;
} else {
server->probe.not_yfs = true;
if (!server->probe.is_yfs) {
clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
alist->addrs[index].srx_service = call->service_id;
}
}
/* Get the RTT and scale it to fit into a 32-bit value that represents
* over a minute of time so that we can access it with one instruction
* on a 32-bit system.
*/
_rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall);
_rtt /= 64;
rtt = (_rtt > UINT_MAX) ? UINT_MAX : _rtt;
if (rtt < server->probe.rtt) {
server->probe.rtt = rtt;
alist->preferred = index;
have_result = true;
}
smp_wmb(); /* Set rtt before responded. */
server->probe.responded = true;
set_bit(AFS_SERVER_FL_PROBED, &server->flags);
out:
spin_unlock(&server->probe_lock);
_debug("probe [%u][%u] %pISpc rtt=%u ret=%d",
server_index, index, &alist->addrs[index].transport,
(unsigned int)rtt, ret);
have_result |= afs_fs_probe_done(server);
if (have_result) {
server->probe.have_result = true;
wake_up_var(&server->probe.have_result);
wake_up_all(&server->probe_wq);
}
}
/*
* Probe all of a fileserver's addresses to find out the best route and to
* query its capabilities.
*/
static int afs_do_probe_fileserver(struct afs_net *net,
struct afs_server *server,
struct key *key,
unsigned int server_index)
{
struct afs_addr_cursor ac = {
.index = 0,
};
int ret;
_enter("%pU", &server->uuid);
read_lock(&server->fs_lock);
ac.alist = rcu_dereference_protected(server->addresses,
lockdep_is_held(&server->fs_lock));
read_unlock(&server->fs_lock);
atomic_set(&server->probe_outstanding, ac.alist->nr_addrs);
memset(&server->probe, 0, sizeof(server->probe));
server->probe.rtt = UINT_MAX;
for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
ret = afs_fs_get_capabilities(net, server, &ac, key, server_index,
true);
if (ret != -EINPROGRESS) {
afs_fs_probe_done(server);
return ret;
}
}
return 0;
}
/*
* Send off probes to all unprobed servers.
*/
int afs_probe_fileservers(struct afs_net *net, struct key *key,
struct afs_server_list *list)
{
struct afs_server *server;
int i, ret;
for (i = 0; i < list->nr_servers; i++) {
server = list->servers[i].server;
if (test_bit(AFS_SERVER_FL_PROBED, &server->flags))
continue;
if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags)) {
ret = afs_do_probe_fileserver(net, server, key, i);
if (ret)
return ret;
}
}
return 0;
}
/*
* Wait for the first as-yet untried fileserver to respond.
*/
int afs_wait_for_fs_probes(struct afs_server_list *slist, unsigned long untried)
{
struct wait_queue_entry *waits;
struct afs_server *server;
unsigned int rtt = UINT_MAX;
bool have_responders = false;
int pref = -1, i;
_enter("%u,%lx", slist->nr_servers, untried);
/* Only wait for servers that have a probe outstanding. */
for (i = 0; i < slist->nr_servers; i++) {
if (test_bit(i, &untried)) {
server = slist->servers[i].server;
if (!test_bit(AFS_SERVER_FL_PROBING, &server->flags))
__clear_bit(i, &untried);
if (server->probe.responded)
have_responders = true;
}
}
if (have_responders || !untried)
return 0;
waits = kmalloc(array_size(slist->nr_servers, sizeof(*waits)), GFP_KERNEL);
if (!waits)
return -ENOMEM;
for (i = 0; i < slist->nr_servers; i++) {
if (test_bit(i, &untried)) {
server = slist->servers[i].server;
init_waitqueue_entry(&waits[i], current);
add_wait_queue(&server->probe_wq, &waits[i]);
}
}
for (;;) {
bool still_probing = false;
set_current_state(TASK_INTERRUPTIBLE);
for (i = 0; i < slist->nr_servers; i++) {
if (test_bit(i, &untried)) {
server = slist->servers[i].server;
if (server->probe.responded)
goto stop;
if (test_bit(AFS_SERVER_FL_PROBING, &server->flags))
still_probing = true;
}
}
if (!still_probing || unlikely(signal_pending(current)))
goto stop;
schedule();
}
stop:
set_current_state(TASK_RUNNING);
for (i = 0; i < slist->nr_servers; i++) {
if (test_bit(i, &untried)) {
server = slist->servers[i].server;
if (server->probe.responded &&
server->probe.rtt < rtt) {
pref = i;
rtt = server->probe.rtt;
}
remove_wait_queue(&server->probe_wq, &waits[i]);
}
}
kfree(waits);
if (pref == -1 && signal_pending(current))
return -ERESTARTSYS;
if (pref >= 0)
slist->preferred = pref;
return 0;
}
此差异已折叠。
......@@ -82,7 +82,7 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key)
default:
printk("kAFS: AFS vnode with undefined type\n");
read_sequnlock_excl(&vnode->cb_lock);
return afs_protocol_error(NULL, -EBADMSG);
return afs_protocol_error(NULL, -EBADMSG, afs_eproto_file_type);
}
inode->i_blocks = 0;
......@@ -100,7 +100,7 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
struct afs_fs_cursor fc;
int ret;
_enter("%s,{%x:%u.%u,S=%lx}",
_enter("%s,{%llx:%llu.%u,S=%lx}",
vnode->volume->name,
vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique,
vnode->flags);
......@@ -127,9 +127,9 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
int afs_iget5_test(struct inode *inode, void *opaque)
{
struct afs_iget_data *data = opaque;
struct afs_vnode *vnode = AFS_FS_I(inode);
return inode->i_ino == data->fid.vnode &&
inode->i_generation == data->fid.unique;
return memcmp(&vnode->fid, &data->fid, sizeof(data->fid)) == 0;
}
/*
......@@ -150,11 +150,14 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
struct afs_iget_data *data = opaque;
struct afs_vnode *vnode = AFS_FS_I(inode);
inode->i_ino = data->fid.vnode;
inode->i_generation = data->fid.unique;
vnode->fid = data->fid;
vnode->volume = data->volume;
/* YFS supports 96-bit vnode IDs, but Linux only supports
* 64-bit inode numbers.
*/
inode->i_ino = data->fid.vnode;
inode->i_generation = data->fid.unique;
return 0;
}
......@@ -193,7 +196,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
return ERR_PTR(-ENOMEM);
}
_debug("GOT INODE %p { ino=%lu, vl=%x, vn=%x, u=%x }",
_debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
inode, inode->i_ino, data.fid.vid, data.fid.vnode,
data.fid.unique);
......@@ -252,8 +255,8 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
key.vnode_id = vnode->fid.vnode;
key.unique = vnode->fid.unique;
key.vnode_id_ext[0] = 0;
key.vnode_id_ext[1] = 0;
key.vnode_id_ext[0] = vnode->fid.vnode >> 32;
key.vnode_id_ext[1] = vnode->fid.vnode_hi;
aux.data_version = vnode->status.data_version;
vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
......@@ -277,7 +280,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
struct inode *inode;
int ret;
_enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique);
_enter(",{%llx:%llu.%u},,", fid->vid, fid->vnode, fid->unique);
as = sb->s_fs_info;
data.volume = as->volume;
......@@ -289,7 +292,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
return ERR_PTR(-ENOMEM);
}
_debug("GOT INODE %p { vl=%x vn=%x, u=%x }",
_debug("GOT INODE %p { vl=%llx vn=%llx, u=%x }",
inode, fid->vid, fid->vnode, fid->unique);
vnode = AFS_FS_I(inode);
......@@ -314,11 +317,11 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
* didn't give us a callback) */
vnode->cb_version = 0;
vnode->cb_type = 0;
vnode->cb_expires_at = 0;
vnode->cb_expires_at = ktime_get();
} else {
vnode->cb_version = cb->version;
vnode->cb_type = cb->type;
vnode->cb_expires_at = cb->expiry;
vnode->cb_expires_at = cb->expires_at;
vnode->cb_interest = afs_get_cb_interest(cbi);
set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
}
......@@ -352,7 +355,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
*/
void afs_zap_data(struct afs_vnode *vnode)
{
_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
_enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
#ifdef CONFIG_AFS_FSCACHE
fscache_invalidate(vnode->cache);
......@@ -382,7 +385,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
bool valid = false;
int ret;
_enter("{v={%x:%u} fl=%lx},%x",
_enter("{v={%llx:%llu} fl=%lx},%x",
vnode->fid.vid, vnode->fid.vnode, vnode->flags,
key_serial(key));
......@@ -501,7 +504,7 @@ void afs_evict_inode(struct inode *inode)
vnode = AFS_FS_I(inode);
_enter("{%x:%u.%d}",
_enter("{%llx:%llu.%d}",
vnode->fid.vid,
vnode->fid.vnode,
vnode->fid.unique);
......@@ -550,7 +553,7 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
struct key *key;
int ret;
_enter("{%x:%u},{n=%pd},%x",
_enter("{%llx:%llu},{n=%pd},%x",
vnode->fid.vid, vnode->fid.vnode, dentry,
attr->ia_valid);
......
此差异已折叠。
......@@ -130,9 +130,10 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
goto error_no_page;
}
ret = -EIO;
if (PageError(page))
if (PageError(page)) {
ret = afs_bad(AFS_FS_I(d_inode(mntpt)), afs_file_error_mntpt);
goto error;
}
buf = kmap_atomic(page);
memcpy(devname, buf, size);
......
......@@ -17,6 +17,11 @@
#include <linux/uaccess.h>
#include "internal.h"
struct afs_vl_seq_net_private {
struct seq_net_private seq; /* Must be first */
struct afs_vlserver_list *vllist;
};
static inline struct afs_net *afs_seq2net(struct seq_file *m)
{
return afs_net(seq_file_net(m));
......@@ -32,16 +37,24 @@ static inline struct afs_net *afs_seq2net_single(struct seq_file *m)
*/
static int afs_proc_cells_show(struct seq_file *m, void *v)
{
struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
struct afs_vlserver_list *vllist;
struct afs_cell *cell;
if (v == SEQ_START_TOKEN) {
/* display header on line 1 */
seq_puts(m, "USE NAME\n");
seq_puts(m, "USE TTL SV NAME\n");
return 0;
}
cell = list_entry(v, struct afs_cell, proc_link);
vllist = rcu_dereference(cell->vl_servers);
/* display one cell per line on subsequent lines */
seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name);
seq_printf(m, "%3u %6lld %2u %s\n",
atomic_read(&cell->usage),
cell->dns_expiry - ktime_get_real_seconds(),
vllist ? vllist->nr_servers : 0,
cell->name);
return 0;
}
......@@ -208,7 +221,7 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
return 0;
}
seq_printf(m, "%3d %08x %s\n",
seq_printf(m, "%3d %08llx %s\n",
atomic_read(&vol->usage), vol->vid,
afs_vol_types[vol->type]);
......@@ -247,61 +260,102 @@ static const struct seq_operations afs_proc_cell_volumes_ops = {
.show = afs_proc_cell_volumes_show,
};
static const char *const dns_record_sources[NR__dns_record_source + 1] = {
[DNS_RECORD_UNAVAILABLE] = "unav",
[DNS_RECORD_FROM_CONFIG] = "cfg",
[DNS_RECORD_FROM_DNS_A] = "A",
[DNS_RECORD_FROM_DNS_AFSDB] = "AFSDB",
[DNS_RECORD_FROM_DNS_SRV] = "SRV",
[DNS_RECORD_FROM_NSS] = "nss",
[NR__dns_record_source] = "[weird]"
};
static const char *const dns_lookup_statuses[NR__dns_lookup_status + 1] = {
[DNS_LOOKUP_NOT_DONE] = "no-lookup",
[DNS_LOOKUP_GOOD] = "good",
[DNS_LOOKUP_GOOD_WITH_BAD] = "good/bad",
[DNS_LOOKUP_BAD] = "bad",
[DNS_LOOKUP_GOT_NOT_FOUND] = "not-found",
[DNS_LOOKUP_GOT_LOCAL_FAILURE] = "local-failure",
[DNS_LOOKUP_GOT_TEMP_FAILURE] = "temp-failure",
[DNS_LOOKUP_GOT_NS_FAILURE] = "ns-failure",
[NR__dns_lookup_status] = "[weird]"
};
/*
* Display the list of Volume Location servers we're using for a cell.
*/
static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
{
struct sockaddr_rxrpc *addr = v;
const struct afs_vl_seq_net_private *priv = m->private;
const struct afs_vlserver_list *vllist = priv->vllist;
const struct afs_vlserver_entry *entry;
const struct afs_vlserver *vlserver;
const struct afs_addr_list *alist;
int i;
/* display header on line 1 */
if (v == (void *)1) {
seq_puts(m, "ADDRESS\n");
if (v == SEQ_START_TOKEN) {
seq_printf(m, "# source %s, status %s\n",
dns_record_sources[vllist->source],
dns_lookup_statuses[vllist->status]);
return 0;
}
/* display one cell per line on subsequent lines */
seq_printf(m, "%pISp\n", &addr->transport);
entry = v;
vlserver = entry->server;
alist = rcu_dereference(vlserver->addresses);
seq_printf(m, "%s [p=%hu w=%hu s=%s,%s]:\n",
vlserver->name, entry->priority, entry->weight,
dns_record_sources[alist ? alist->source : entry->source],
dns_lookup_statuses[alist ? alist->status : entry->status]);
if (alist) {
for (i = 0; i < alist->nr_addrs; i++)
seq_printf(m, " %c %pISpc\n",
alist->preferred == i ? '>' : '-',
&alist->addrs[i].transport);
}
return 0;
}
static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
struct afs_addr_list *alist;
struct afs_vl_seq_net_private *priv = m->private;
struct afs_vlserver_list *vllist;
struct afs_cell *cell = PDE_DATA(file_inode(m->file));
loff_t pos = *_pos;
rcu_read_lock();
alist = rcu_dereference(cell->vl_addrs);
vllist = rcu_dereference(cell->vl_servers);
priv->vllist = vllist;
/* allow for the header line */
if (!pos)
return (void *) 1;
pos--;
if (pos < 0)
*_pos = pos = 0;
if (pos == 0)
return SEQ_START_TOKEN;
if (!alist || pos >= alist->nr_addrs)
if (!vllist || pos - 1 >= vllist->nr_servers)
return NULL;
return alist->addrs + pos;
return &vllist->servers[pos - 1];
}
static void *afs_proc_cell_vlservers_next(struct seq_file *m, void *v,
loff_t *_pos)
{
struct afs_addr_list *alist;
struct afs_cell *cell = PDE_DATA(file_inode(m->file));
struct afs_vl_seq_net_private *priv = m->private;
struct afs_vlserver_list *vllist = priv->vllist;
loff_t pos;
alist = rcu_dereference(cell->vl_addrs);
pos = *_pos;
(*_pos)++;
if (!alist || pos >= alist->nr_addrs)
pos++;
*_pos = pos;
if (!vllist || pos - 1 >= vllist->nr_servers)
return NULL;
return alist->addrs + pos;
return &vllist->servers[pos - 1];
}
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)
&server->uuid,
atomic_read(&server->usage),
&alist->addrs[0].transport,
alist->index == 0 ? "*" : "");
alist->preferred == 0 ? "*" : "");
for (i = 1; i < alist->nr_addrs; i++)
seq_printf(m, " %pISpc%s\n",
&alist->addrs[i].transport,
alist->index == i ? "*" : "");
alist->preferred == i ? "*" : "");
return 0;
}
......@@ -562,7 +616,7 @@ int afs_proc_cell_setup(struct afs_cell *cell)
if (!proc_create_net_data("vlservers", 0444, dir,
&afs_proc_cell_vlservers_ops,
sizeof(struct seq_net_private),
sizeof(struct afs_vl_seq_net_private),
cell) ||
!proc_create_net_data("volumes", 0444, dir,
&afs_proc_cell_volumes_ops,
......
/* YFS protocol bits
*
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#define YFS_FS_SERVICE 2500
#define YFS_CM_SERVICE 2501
#define YFSCBMAX 1024
enum YFS_CM_Operations {
YFSCBProbe = 206, /* probe client */
YFSCBGetLock = 207, /* get contents of CM lock table */
YFSCBXStatsVersion = 209, /* get version of extended statistics */
YFSCBGetXStats = 210, /* get contents of extended statistics data */
YFSCBInitCallBackState3 = 213, /* initialise callback state, version 3 */
YFSCBProbeUuid = 214, /* check the client hasn't rebooted */
YFSCBGetServerPrefs = 215,
YFSCBGetCellServDV = 216,
YFSCBGetLocalCell = 217,
YFSCBGetCacheConfig = 218,
YFSCBGetCellByNum = 65537,
YFSCBTellMeAboutYourself = 65538, /* get client capabilities */
YFSCBCallBack = 64204,
};
enum YFS_FS_Operations {
YFSFETCHACL = 64131, /* YFS Fetch file ACL */
YFSFETCHSTATUS = 64132, /* YFS Fetch file status */
YFSSTOREACL = 64134, /* YFS Store file ACL */
YFSSTORESTATUS = 64135, /* YFS Store file status */
YFSREMOVEFILE = 64136, /* YFS Remove a file */
YFSCREATEFILE = 64137, /* YFS Create a file */
YFSRENAME = 64138, /* YFS Rename or move a file or directory */
YFSSYMLINK = 64139, /* YFS Create a symbolic link */
YFSLINK = 64140, /* YFS Create a hard link */
YFSMAKEDIR = 64141, /* YFS Create a directory */
YFSREMOVEDIR = 64142, /* YFS Remove a directory */
YFSGETVOLUMESTATUS = 64149, /* YFS Get volume status information */
YFSSETVOLUMESTATUS = 64150, /* YFS Set volume status information */
YFSSETLOCK = 64156, /* YFS Request a file lock */
YFSEXTENDLOCK = 64157, /* YFS Extend a file lock */
YFSRELEASELOCK = 64158, /* YFS Release a file lock */
YFSLOOKUP = 64161, /* YFS lookup file in directory */
YFSFLUSHCPS = 64165,
YFSFETCHOPAQUEACL = 64168,
YFSWHOAMI = 64170,
YFSREMOVEACL = 64171,
YFSREMOVEFILE2 = 64173,
YFSSTOREOPAQUEACL2 = 64174,
YFSINLINEBULKSTATUS = 64536, /* YFS Fetch multiple file statuses with errors */
YFSFETCHDATA64 = 64537, /* YFS Fetch file data */
YFSSTOREDATA64 = 64538, /* YFS Store file data */
YFSUPDATESYMLINK = 64540,
};
struct yfs_xdr_u64 {
__be32 msw;
__be32 lsw;
} __packed;
static inline u64 xdr_to_u64(const struct yfs_xdr_u64 x)
{
return ((u64)ntohl(x.msw) << 32) | ntohl(x.lsw);
}
static inline struct yfs_xdr_u64 u64_to_xdr(const u64 x)
{
return (struct yfs_xdr_u64){ .msw = htonl(x >> 32), .lsw = htonl(x) };
}
struct yfs_xdr_vnode {
struct yfs_xdr_u64 lo;
__be32 hi;
__be32 unique;
} __packed;
struct yfs_xdr_YFSFid {
struct yfs_xdr_u64 volume;
struct yfs_xdr_vnode vnode;
} __packed;
struct yfs_xdr_YFSFetchStatus {
__be32 type;
__be32 nlink;
struct yfs_xdr_u64 size;
struct yfs_xdr_u64 data_version;
struct yfs_xdr_u64 author;
struct yfs_xdr_u64 owner;
struct yfs_xdr_u64 group;
__be32 mode;
__be32 caller_access;
__be32 anon_access;
struct yfs_xdr_vnode parent;
__be32 data_access_protocol;
struct yfs_xdr_u64 mtime_client;
struct yfs_xdr_u64 mtime_server;
__be32 lock_count;
__be32 abort_code;
} __packed;
struct yfs_xdr_YFSCallBack {
__be32 version;
struct yfs_xdr_u64 expiration_time;
__be32 type;
} __packed;
struct yfs_xdr_YFSStoreStatus {
__be32 mask;
__be32 mode;
struct yfs_xdr_u64 mtime_client;
struct yfs_xdr_u64 owner;
struct yfs_xdr_u64 group;
} __packed;
struct yfs_xdr_RPCFlags {
__be32 rpc_flags;
} __packed;
struct yfs_xdr_YFSVolSync {
struct yfs_xdr_u64 vol_creation_date;
struct yfs_xdr_u64 vol_update_date;
struct yfs_xdr_u64 max_quota;
struct yfs_xdr_u64 blocks_in_use;
struct yfs_xdr_u64 blocks_avail;
} __packed;
enum yfs_volume_type {
yfs_volume_type_ro = 0,
yfs_volume_type_rw = 1,
};
#define yfs_FVSOnline 0x1
#define yfs_FVSInservice 0x2
#define yfs_FVSBlessed 0x4
#define yfs_FVSNeedsSalvage 0x8
struct yfs_xdr_YFSFetchVolumeStatus {
struct yfs_xdr_u64 vid;
struct yfs_xdr_u64 parent_id;
__be32 flags;
__be32 type;
struct yfs_xdr_u64 max_quota;
struct yfs_xdr_u64 blocks_in_use;
struct yfs_xdr_u64 part_blocks_avail;
struct yfs_xdr_u64 part_max_blocks;
struct yfs_xdr_u64 vol_copy_date;
struct yfs_xdr_u64 vol_backup_date;
} __packed;
struct yfs_xdr_YFSStoreVolumeStatus {
__be32 mask;
struct yfs_xdr_u64 min_quota;
struct yfs_xdr_u64 max_quota;
struct yfs_xdr_u64 file_quota;
} __packed;
......@@ -18,14 +18,6 @@
#include "internal.h"
#include "afs_fs.h"
/*
* Initialise a filesystem server cursor for iterating over FS servers.
*/
static void afs_init_fs_cursor(struct afs_fs_cursor *fc, struct afs_vnode *vnode)
{
memset(fc, 0, sizeof(*fc));
}
/*
* Begin an operation on the fileserver.
*
......@@ -35,13 +27,14 @@ static void afs_init_fs_cursor(struct afs_fs_cursor *fc, struct afs_vnode *vnode
bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
struct key *key)
{
afs_init_fs_cursor(fc, vnode);
memset(fc, 0, sizeof(*fc));
fc->vnode = vnode;
fc->key = key;
fc->ac.error = SHRT_MAX;
fc->error = -EDESTADDRREQ;
if (mutex_lock_interruptible(&vnode->io_lock) < 0) {
fc->ac.error = -EINTR;
fc->error = -EINTR;
fc->flags |= AFS_FS_CURSOR_STOP;
return false;
}
......@@ -65,12 +58,15 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,
fc->server_list = afs_get_serverlist(vnode->volume->servers);
read_unlock(&vnode->volume->servers_lock);
fc->untried = (1UL << fc->server_list->nr_servers) - 1;
fc->index = READ_ONCE(fc->server_list->preferred);
cbi = vnode->cb_interest;
if (cbi) {
/* See if the vnode's preferred record is still available */
for (i = 0; i < fc->server_list->nr_servers; i++) {
if (fc->server_list->servers[i].cb_interest == cbi) {
fc->start = i;
fc->index = i;
goto found_interest;
}
}
......@@ -80,7 +76,7 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,
* and have to return an error.
*/
if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) {
fc->ac.error = -ESTALE;
fc->error = -ESTALE;
return false;
}
......@@ -94,12 +90,9 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,
afs_put_cb_interest(afs_v2net(vnode), cbi);
cbi = NULL;
} else {
fc->start = READ_ONCE(fc->server_list->index);
}
found_interest:
fc->index = fc->start;
return true;
}
......@@ -117,7 +110,7 @@ static void afs_busy(struct afs_volume *volume, u32 abort_code)
default: m = "busy"; break;
}
pr_notice("kAFS: Volume %u '%s' is %s\n", volume->vid, volume->name, m);
pr_notice("kAFS: Volume %llu '%s' is %s\n", volume->vid, volume->name, m);
}
/*
......@@ -127,7 +120,7 @@ static bool afs_sleep_and_retry(struct afs_fs_cursor *fc)
{
msleep_interruptible(1000);
if (signal_pending(current)) {
fc->ac.error = -ERESTARTSYS;
fc->error = -ERESTARTSYS;
return false;
}
......@@ -143,27 +136,32 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
struct afs_addr_list *alist;
struct afs_server *server;
struct afs_vnode *vnode = fc->vnode;
u32 rtt, abort_code;
int error = fc->ac.error, i;
_enter("%u/%u,%u/%u,%d,%d",
fc->index, fc->start,
fc->ac.index, fc->ac.start,
fc->ac.error, fc->ac.abort_code);
_enter("%lx[%d],%lx[%d],%d,%d",
fc->untried, fc->index,
fc->ac.tried, fc->ac.index,
error, fc->ac.abort_code);
if (fc->flags & AFS_FS_CURSOR_STOP) {
_leave(" = f [stopped]");
return false;
}
fc->nr_iterations++;
/* Evaluate the result of the previous operation, if there was one. */
switch (fc->ac.error) {
switch (error) {
case SHRT_MAX:
goto start;
case 0:
default:
/* Success or local failure. Stop. */
fc->error = error;
fc->flags |= AFS_FS_CURSOR_STOP;
_leave(" = f [okay/local %d]", fc->ac.error);
_leave(" = f [okay/local %d]", error);
return false;
case -ECONNABORTED:
......@@ -178,7 +176,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
* - May indicate that the fileserver couldn't attach to the vol.
*/
if (fc->flags & AFS_FS_CURSOR_VNOVOL) {
fc->ac.error = -EREMOTEIO;
fc->error = -EREMOTEIO;
goto next_server;
}
......@@ -187,12 +185,12 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
write_unlock(&vnode->volume->servers_lock);
set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags);
fc->ac.error = afs_check_volume_status(vnode->volume, fc->key);
if (fc->ac.error < 0)
goto failed;
error = afs_check_volume_status(vnode->volume, fc->key);
if (error < 0)
goto failed_set_error;
if (test_bit(AFS_VOLUME_DELETED, &vnode->volume->flags)) {
fc->ac.error = -ENOMEDIUM;
fc->error = -ENOMEDIUM;
goto failed;
}
......@@ -200,7 +198,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
* it's the fileserver having trouble.
*/
if (vnode->volume->servers == fc->server_list) {
fc->ac.error = -EREMOTEIO;
fc->error = -EREMOTEIO;
goto next_server;
}
......@@ -215,7 +213,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
case VONLINE:
case VDISKFULL:
case VOVERQUOTA:
fc->ac.error = afs_abort_to_error(fc->ac.abort_code);
fc->error = afs_abort_to_error(fc->ac.abort_code);
goto next_server;
case VOFFLINE:
......@@ -224,11 +222,11 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags);
}
if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) {
fc->ac.error = -EADV;
fc->error = -EADV;
goto failed;
}
if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) {
fc->ac.error = -ESTALE;
fc->error = -ESTALE;
goto failed;
}
goto busy;
......@@ -240,7 +238,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
* have a file lock we need to maintain.
*/
if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) {
fc->ac.error = -EBUSY;
fc->error = -EBUSY;
goto failed;
}
if (!test_and_set_bit(AFS_VOLUME_BUSY, &vnode->volume->flags)) {
......@@ -269,16 +267,16 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
* honour, just in case someone sets up a loop.
*/
if (fc->flags & AFS_FS_CURSOR_VMOVED) {
fc->ac.error = -EREMOTEIO;
fc->error = -EREMOTEIO;
goto failed;
}
fc->flags |= AFS_FS_CURSOR_VMOVED;
set_bit(AFS_VOLUME_WAIT, &vnode->volume->flags);
set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags);
fc->ac.error = afs_check_volume_status(vnode->volume, fc->key);
if (fc->ac.error < 0)
goto failed;
error = afs_check_volume_status(vnode->volume, fc->key);
if (error < 0)
goto failed_set_error;
/* If the server list didn't change, then the VLDB is
* out of sync with the fileservers. This is hopefully
......@@ -290,7 +288,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
* TODO: Retry a few times with sleeps.
*/
if (vnode->volume->servers == fc->server_list) {
fc->ac.error = -ENOMEDIUM;
fc->error = -ENOMEDIUM;
goto failed;
}
......@@ -299,20 +297,25 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
default:
clear_bit(AFS_VOLUME_OFFLINE, &vnode->volume->flags);
clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags);
fc->ac.error = afs_abort_to_error(fc->ac.abort_code);
fc->error = afs_abort_to_error(fc->ac.abort_code);
goto failed;
}
case -ETIMEDOUT:
case -ETIME:
if (fc->error != -EDESTADDRREQ)
goto iterate_address;
/* Fall through */
case -ENETUNREACH:
case -EHOSTUNREACH:
case -ECONNREFUSED:
case -ETIMEDOUT:
case -ETIME:
_debug("no conn");
fc->error = error;
goto iterate_address;
case -ECONNRESET:
_debug("call reset");
fc->error = error;
goto failed;
}
......@@ -328,15 +331,57 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
/* See if we need to do an update of the volume record. Note that the
* volume may have moved or even have been deleted.
*/
fc->ac.error = afs_check_volume_status(vnode->volume, fc->key);
if (fc->ac.error < 0)
goto failed;
error = afs_check_volume_status(vnode->volume, fc->key);
if (error < 0)
goto failed_set_error;
if (!afs_start_fs_iteration(fc, vnode))
goto failed;
use_server:
_debug("use");
_debug("__ VOL %llx __", vnode->volume->vid);
error = afs_probe_fileservers(afs_v2net(vnode), fc->key, fc->server_list);
if (error < 0)
goto failed_set_error;
pick_server:
_debug("pick [%lx]", fc->untried);
error = afs_wait_for_fs_probes(fc->server_list, fc->untried);
if (error < 0)
goto failed_set_error;
/* Pick the untried server with the lowest RTT. If we have outstanding
* callbacks, we stick with the server we're already using if we can.
*/
if (fc->cbi) {
_debug("cbi %u", fc->index);
if (test_bit(fc->index, &fc->untried))
goto selected_server;
afs_put_cb_interest(afs_v2net(vnode), fc->cbi);
fc->cbi = NULL;
_debug("nocbi");
}
fc->index = -1;
rtt = U32_MAX;
for (i = 0; i < fc->server_list->nr_servers; i++) {
struct afs_server *s = fc->server_list->servers[i].server;
if (!test_bit(i, &fc->untried) || !s->probe.responded)
continue;
if (s->probe.rtt < rtt) {
fc->index = i;
rtt = s->probe.rtt;
}
}
if (fc->index == -1)
goto no_more_servers;
selected_server:
_debug("use %d", fc->index);
__clear_bit(fc->index, &fc->untried);
/* We're starting on a different fileserver from the list. We need to
* check it, create a callback intercept, find its address list and
* probe its capabilities before we use it.
......@@ -354,10 +399,10 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
* break request before we've finished decoding the reply and
* installing the vnode.
*/
fc->ac.error = afs_register_server_cb_interest(vnode, fc->server_list,
fc->index);
if (fc->ac.error < 0)
goto failed;
error = afs_register_server_cb_interest(vnode, fc->server_list,
fc->index);
if (error < 0)
goto failed_set_error;
fc->cbi = afs_get_cb_interest(vnode->cb_interest);
......@@ -369,66 +414,88 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
memset(&fc->ac, 0, sizeof(fc->ac));
/* Probe the current fileserver if we haven't done so yet. */
if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) {
fc->ac.alist = afs_get_addrlist(alist);
if (!afs_probe_fileserver(fc)) {
switch (fc->ac.error) {
case -ENOMEM:
case -ERESTARTSYS:
case -EINTR:
goto failed;
default:
goto next_server;
}
}
}
if (!fc->ac.alist)
fc->ac.alist = alist;
else
afs_put_addrlist(alist);
fc->ac.start = READ_ONCE(alist->index);
fc->ac.index = fc->ac.start;
fc->ac.index = -1;
iterate_address:
ASSERT(fc->ac.alist);
_debug("iterate %d/%d", fc->ac.index, fc->ac.alist->nr_addrs);
/* Iterate over the current server's address list to try and find an
* address on which it will respond to us.
*/
if (!afs_iterate_addresses(&fc->ac))
goto next_server;
_debug("address [%u] %u/%u", fc->index, fc->ac.index, fc->ac.alist->nr_addrs);
_leave(" = t");
return true;
next_server:
_debug("next");
afs_end_cursor(&fc->ac);
afs_put_cb_interest(afs_v2net(vnode), fc->cbi);
fc->cbi = NULL;
fc->index++;
if (fc->index >= fc->server_list->nr_servers)
fc->index = 0;
if (fc->index != fc->start)
goto use_server;
goto pick_server;
no_more_servers:
/* That's all the servers poked to no good effect. Try again if some
* of them were busy.
*/
if (fc->flags & AFS_FS_CURSOR_VBUSY)
goto restart_from_beginning;
fc->ac.error = -EDESTADDRREQ;
goto failed;
abort_code = 0;
error = -EDESTADDRREQ;
for (i = 0; i < fc->server_list->nr_servers; i++) {
struct afs_server *s = fc->server_list->servers[i].server;
int probe_error = READ_ONCE(s->probe.error);
switch (probe_error) {
case 0:
continue;
default:
if (error == -ETIMEDOUT ||
error == -ETIME)
continue;
case -ETIMEDOUT:
case -ETIME:
if (error == -ENOMEM ||
error == -ENONET)
continue;
case -ENOMEM:
case -ENONET:
if (error == -ENETUNREACH)
continue;
case -ENETUNREACH:
if (error == -EHOSTUNREACH)
continue;
case -EHOSTUNREACH:
if (error == -ECONNREFUSED)
continue;
case -ECONNREFUSED:
if (error == -ECONNRESET)
continue;
case -ECONNRESET: /* Responded, but call expired. */
if (error == -ECONNABORTED)
continue;
case -ECONNABORTED:
abort_code = s->probe.abort_code;
error = probe_error;
continue;
}
}
if (error == -ECONNABORTED)
error = afs_abort_to_error(abort_code);
failed_set_error:
fc->error = error;
failed:
fc->flags |= AFS_FS_CURSOR_STOP;
afs_end_cursor(&fc->ac);
_leave(" = f [failed %d]", fc->ac.error);
_leave(" = f [failed %d]", fc->error);
return false;
}
......@@ -442,13 +509,14 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
struct afs_vnode *vnode = fc->vnode;
struct afs_cb_interest *cbi = vnode->cb_interest;
struct afs_addr_list *alist;
int error = fc->ac.error;
_enter("");
switch (fc->ac.error) {
switch (error) {
case SHRT_MAX:
if (!cbi) {
fc->ac.error = -ESTALE;
fc->error = -ESTALE;
fc->flags |= AFS_FS_CURSOR_STOP;
return false;
}
......@@ -461,25 +529,26 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
afs_get_addrlist(alist);
read_unlock(&cbi->server->fs_lock);
if (!alist) {
fc->ac.error = -ESTALE;
fc->error = -ESTALE;
fc->flags |= AFS_FS_CURSOR_STOP;
return false;
}
memset(&fc->ac, 0, sizeof(fc->ac));
fc->ac.alist = alist;
fc->ac.start = READ_ONCE(alist->index);
fc->ac.index = fc->ac.start;
fc->ac.index = -1;
goto iterate_address;
case 0:
default:
/* Success or local failure. Stop. */
fc->error = error;
fc->flags |= AFS_FS_CURSOR_STOP;
_leave(" = f [okay/local %d]", fc->ac.error);
_leave(" = f [okay/local %d]", error);
return false;
case -ECONNABORTED:
fc->error = afs_abort_to_error(fc->ac.abort_code);
fc->flags |= AFS_FS_CURSOR_STOP;
_leave(" = f [abort]");
return false;
......@@ -490,6 +559,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
case -ETIMEDOUT:
case -ETIME:
_debug("no conn");
fc->error = error;
goto iterate_address;
}
......@@ -506,13 +576,66 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
return false;
}
/*
* Dump cursor state in the case of the error being EDESTADDRREQ.
*/
static void afs_dump_edestaddrreq(const struct afs_fs_cursor *fc)
{
static int count;
int i;
if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3)
return;
count++;
rcu_read_lock();
pr_notice("EDESTADDR occurred\n");
pr_notice("FC: cbb=%x cbb2=%x fl=%hx err=%hd\n",
fc->cb_break, fc->cb_break_2, fc->flags, fc->error);
pr_notice("FC: ut=%lx ix=%d ni=%u\n",
fc->untried, fc->index, fc->nr_iterations);
if (fc->server_list) {
const struct afs_server_list *sl = fc->server_list;
pr_notice("FC: SL nr=%u pr=%u vnov=%hx\n",
sl->nr_servers, sl->preferred, sl->vnovol_mask);
for (i = 0; i < sl->nr_servers; i++) {
const struct afs_server *s = sl->servers[i].server;
pr_notice("FC: server fl=%lx av=%u %pU\n",
s->flags, s->addr_version, &s->uuid);
if (s->addresses) {
const struct afs_addr_list *a =
rcu_dereference(s->addresses);
pr_notice("FC: - av=%u nr=%u/%u/%u pr=%u\n",
a->version,
a->nr_ipv4, a->nr_addrs, a->max_addrs,
a->preferred);
pr_notice("FC: - pr=%lx R=%lx F=%lx\n",
a->probed, a->responded, a->failed);
if (a == fc->ac.alist)
pr_notice("FC: - current\n");
}
}
}
pr_notice("AC: t=%lx ax=%u ac=%d er=%d r=%u ni=%u\n",
fc->ac.tried, fc->ac.index, fc->ac.abort_code, fc->ac.error,
fc->ac.responded, fc->ac.nr_iterations);
rcu_read_unlock();
}
/*
* Tidy up a filesystem cursor and unlock the vnode.
*/
int afs_end_vnode_operation(struct afs_fs_cursor *fc)
{
struct afs_net *net = afs_v2net(fc->vnode);
int ret;
if (fc->error == -EDESTADDRREQ ||
fc->error == -ENETUNREACH ||
fc->error == -EHOSTUNREACH)
afs_dump_edestaddrreq(fc);
mutex_unlock(&fc->vnode->io_lock);
......@@ -520,9 +643,8 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc)
afs_put_cb_interest(net, fc->cbi);
afs_put_serverlist(net, fc->server_list);
ret = fc->ac.error;
if (ret == -ECONNABORTED)
afs_abort_to_error(fc->ac.abort_code);
if (fc->error == -ECONNABORTED)
fc->error = afs_abort_to_error(fc->ac.abort_code);
return fc->ac.error;
return fc->error;
}
此差异已折叠。
......@@ -126,7 +126,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
bool changed = false;
int i, j;
_enter("{%x:%u},%x,%x",
_enter("{%llx:%llu},%x,%x",
vnode->fid.vid, vnode->fid.vnode, key_serial(key), caller_access);
rcu_read_lock();
......@@ -147,7 +147,8 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
break;
}
if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest)) {
if (afs_cb_is_broken(cb_break, vnode,
vnode->cb_interest)) {
changed = true;
break;
}
......@@ -177,7 +178,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
}
}
if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest))
if (afs_cb_is_broken(cb_break, vnode, vnode->cb_interest))
goto someone_else_changed_it;
/* We need a ref on any permits list we want to copy as we'll have to
......@@ -256,7 +257,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
spin_lock(&vnode->lock);
zap = rcu_access_pointer(vnode->permit_cache);
if (cb_break == afs_cb_break_sum(vnode, vnode->cb_interest) &&
if (!afs_cb_is_broken(cb_break, vnode, vnode->cb_interest) &&
zap == permits)
rcu_assign_pointer(vnode->permit_cache, replacement);
else
......@@ -289,7 +290,7 @@ int afs_check_permit(struct afs_vnode *vnode, struct key *key,
bool valid = false;
int i, ret;
_enter("{%x:%u},%x",
_enter("{%llx:%llu},%x",
vnode->fid.vid, vnode->fid.vnode, key_serial(key));
/* check the permits to see if we've got one yet */
......@@ -349,7 +350,7 @@ int afs_permission(struct inode *inode, int mask)
if (mask & MAY_NOT_BLOCK)
return -ECHILD;
_enter("{{%x:%u},%lx},%x,",
_enter("{{%llx:%llu},%lx},%x,",
vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask);
key = afs_request_key(vnode->volume->cell);
......
此差异已折叠。
......@@ -118,11 +118,11 @@ bool afs_annotate_server_list(struct afs_server_list *new,
return false;
changed:
/* Maintain the same current server as before if possible. */
cur = old->servers[old->index].server;
/* Maintain the same preferred server as before if possible. */
cur = old->servers[old->preferred].server;
for (j = 0; j < new->nr_servers; j++) {
if (new->servers[j].server == cur) {
new->index = j;
new->preferred = j;
break;
}
}
......
......@@ -406,10 +406,11 @@ static int afs_fill_super(struct super_block *sb,
inode = afs_iget_pseudo_dir(sb, true);
sb->s_flags |= SB_RDONLY;
} else {
sprintf(sb->s_id, "%u", as->volume->vid);
sprintf(sb->s_id, "%llu", as->volume->vid);
afs_activate_volume(as->volume);
fid.vid = as->volume->vid;
fid.vnode = 1;
fid.vnode_hi = 0;
fid.unique = 1;
inode = afs_iget(sb, params->key, &fid, NULL, NULL, NULL);
}
......@@ -663,7 +664,7 @@ static void afs_destroy_inode(struct inode *inode)
{
struct afs_vnode *vnode = AFS_FS_I(inode);
_enter("%p{%x:%u}", inode, vnode->fid.vid, vnode->fid.vnode);
_enter("%p{%llx:%llu}", inode, vnode->fid.vid, vnode->fid.vnode);
_debug("DESTROY INODE %p", inode);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -74,55 +74,19 @@ static struct afs_vldb_entry *afs_vl_lookup_vldb(struct afs_cell *cell,
const char *volname,
size_t volnamesz)
{
struct afs_addr_cursor ac;
struct afs_vldb_entry *vldb;
struct afs_vldb_entry *vldb = ERR_PTR(-EDESTADDRREQ);
struct afs_vl_cursor vc;
int ret;
ret = afs_set_vl_cursor(&ac, cell);
if (ret < 0)
return ERR_PTR(ret);
while (afs_iterate_addresses(&ac)) {
if (!test_bit(ac.index, &ac.alist->probed)) {
ret = afs_vl_get_capabilities(cell->net, &ac, key);
switch (ret) {
case VL_SERVICE:
clear_bit(ac.index, &ac.alist->yfs);
set_bit(ac.index, &ac.alist->probed);
ac.addr->srx_service = ret;
break;
case YFS_VL_SERVICE:
set_bit(ac.index, &ac.alist->yfs);
set_bit(ac.index, &ac.alist->probed);
ac.addr->srx_service = ret;
break;
}
}
vldb = afs_vl_get_entry_by_name_u(cell->net, &ac, key,
volname, volnamesz);
switch (ac.error) {
case 0:
afs_end_cursor(&ac);
return vldb;
case -ECONNABORTED:
ac.error = afs_abort_to_error(ac.abort_code);
goto error;
case -ENOMEM:
case -ENONET:
goto error;
case -ENETUNREACH:
case -EHOSTUNREACH:
case -ECONNREFUSED:
break;
default:
ac.error = -EIO;
goto error;
}
if (!afs_begin_vlserver_operation(&vc, cell, key))
return ERR_PTR(-ERESTARTSYS);
while (afs_select_vlserver(&vc)) {
vldb = afs_vl_get_entry_by_name_u(&vc, volname, volnamesz);
}
error:
return ERR_PTR(afs_end_cursor(&ac));
ret = afs_end_vlserver_operation(&vc);
return ret < 0 ? ERR_PTR(ret) : vldb;
}
/*
......@@ -270,7 +234,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
/* We look up an ID by passing it as a decimal string in the
* operation's name parameter.
*/
idsz = sprintf(idbuf, "%u", volume->vid);
idsz = sprintf(idbuf, "%llu", volume->vid);
vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz);
if (IS_ERR(vldb)) {
......
此差异已折叠。
......@@ -72,7 +72,7 @@ static int afs_xattr_get_fid(const struct xattr_handler *handler,
char text[8 + 1 + 8 + 1 + 8 + 1];
size_t len;
len = sprintf(text, "%x:%x:%x",
len = sprintf(text, "%llx:%llx:%x",
vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
if (size == 0)
return len;
......
此差异已折叠。
......@@ -349,7 +349,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
dio->size = 0;
dio->multi_bio = false;
dio->should_dirty = is_read && (iter->type == ITER_IOVEC);
dio->should_dirty = is_read && iter_is_iovec(iter);
blk_start_plug(&plug);
for (;;) {
......
......@@ -615,7 +615,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to,
more = len < iov_iter_count(to);
if (unlikely(to->type & ITER_PIPE)) {
if (unlikely(iov_iter_is_pipe(to))) {
ret = iov_iter_get_pages_alloc(to, &pages, len,
&page_off);
if (ret <= 0) {
......@@ -662,7 +662,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to,
ret += zlen;
}
if (unlikely(to->type & ITER_PIPE)) {
if (unlikely(iov_iter_is_pipe(to))) {
if (ret > 0) {
iov_iter_advance(to, ret);
off += ret;
......@@ -815,7 +815,7 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req)
aio_req->total_len = rc + zlen;
}
iov_iter_bvec(&i, ITER_BVEC, osd_data->bvec_pos.bvecs,
iov_iter_bvec(&i, READ, osd_data->bvec_pos.bvecs,
osd_data->num_bvecs,
osd_data->bvec_pos.iter.bi_size);
iov_iter_advance(&i, rc);
......@@ -1038,8 +1038,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
int zlen = min_t(size_t, len - ret,
size - pos - ret);
iov_iter_bvec(&i, ITER_BVEC, bvecs, num_pages,
len);
iov_iter_bvec(&i, READ, bvecs, num_pages, len);
iov_iter_advance(&i, ret);
iov_iter_zero(zlen, &i);
ret += zlen;
......
......@@ -589,7 +589,7 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
{
struct msghdr smb_msg;
struct kvec iov = {.iov_base = buf, .iov_len = to_read};
iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
return cifs_readv_from_socket(server, &smb_msg);
}
......@@ -601,7 +601,7 @@ cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
struct msghdr smb_msg;
struct bio_vec bv = {
.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
return cifs_readv_from_socket(server, &smb_msg);
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册