mirror of https://gitee.com/openkylin/linux.git
AFS fixes
-----BEGIN PGP SIGNATURE----- iQIVAwUAWvmaZvu3V2unywtrAQKZoA/9HzO6QsB7h7hWY6tTuoL0gD8T8S4hC7l3 UYFtTgq0rFHJYiET4SWoy0Sfs8rY1iFPtaIeFVQG804SrnXu5/Q1tsv+1lRhZIuo /upAtZ3xEcqvAqU8pgcksKl/KUdmm7ZHUbhAFCasu+1eczGF5Q55UAUgonFrnEMi 9N0WviRUkRAlTre7cvCMRI05c+HJV+PCYrJPjStAkJeuS1CuTEAT/d58NumquMAt 6ENkpR4OhRUJZDhYH7XIRLm7hsYjr9v3VIeCiLpYqUZGuvhaj3jzPi0e9zD5PDzZ lyyodQVegBs88V2rXrjjZHohNQRiuSzI+42pMXrdaDu5jBFFqYLEeaBoperJY7nl W6l6HSb/I8VValM7iwkyzNWeQ6KhdUhYvA5ljYaJufZvqxp4di9xT4mAxRqbHSX+ H5I/n+R27FEOFAqnWInaksj5IO80HGThrGhdz9O/4pa8xITz7W2ZKg5YMLEoF9yp /QUxsn3lz4VD4tjPrqampJ+IwbpQB+XDiJhM4boI47kC2IxEc9L2QiYWlFl/okZ4 CGuXsluQFPleR3Mo8xq1WaQzmT40iYQ+aBOPq1/OhDisexZJ55Cjha1GHk/8aHDu GL5UiL7AfWEwY20mJiCObg8u2nnkwg/0YPR3awDBlCMDBeYhxbSFOLrKiQxUjWM9 Pp6PUhTtSjU= =1ow3 -----END PGP SIGNATURE----- Merge tag 'afs-fixes-20180514' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs Pull AFS fixes from David Howells: "Here's a set of patches that fix a number of bugs in the in-kernel AFS client, including: - Fix directory locking to not use individual page locks for directory reading/scanning but rather to use a semaphore on the afs_vnode struct as the directory contents must be read in a single blob and data from different reads must not be mixed as the entire contents may be shuffled about between reads. - Fix address list parsing to handle port specifiers correctly. - Only give up callback records on a server if we actually talked to that server (we might not be able to access a server). - Fix some callback handling bugs, including refcounting, whole-volume callbacks and when callbacks actually get broken in response to a CB.CallBack op. - Fix some server/address rotation bugs, including giving up if we can't probe a server; giving up if a server says it doesn't have a volume, but there are more servers to try. - Fix the decoding of fetched statuses to be OpenAFS compatible. - Fix the handling of server lookups in Cache Manager ops (such as CB.InitCallBackState3) to use a UUID if possible and to handle no server being found. - Fix a bug in server lookup where not all addresses are compared. - Fix the non-encryption of calls that prevents some servers from being accessed (this also requires an AF_RXRPC patch that has already gone in through the net tree). There's also a patch that adds tracepoints to log Cache Manager ops that don't find a matching server, either by UUID or by address" * tag 'afs-fixes-20180514' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Fix the non-encryption of calls afs: Fix CB.CallBack handling afs: Fix whole-volume callback handling afs: Fix afs_find_server search loop afs: Fix the handling of an unfound server in CM operations afs: Add a tracepoint to record callbacks from unlisted servers afs: Fix the handling of CB.InitCallBackState3 to find the server by UUID afs: Fix VNOVOL handling in address rotation afs: Fix AFSFetchStatus decoder to provide OpenAFS compatibility afs: Fix server rotation's handling of fileserver probe failure afs: Fix refcounting in callback registration afs: Fix giving up callbacks on server destruction afs: Fix address list parsing afs: Fix directory page locking
This commit is contained in:
commit
21b9f1c7e3
|
@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
|
|||
p = text;
|
||||
do {
|
||||
struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs];
|
||||
char tdelim = delim;
|
||||
const char *q, *stop;
|
||||
|
||||
if (*p == delim) {
|
||||
p++;
|
||||
|
@ -130,28 +130,33 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
|
|||
|
||||
if (*p == '[') {
|
||||
p++;
|
||||
tdelim = ']';
|
||||
q = memchr(p, ']', end - p);
|
||||
} else {
|
||||
for (q = p; q < end; q++)
|
||||
if (*q == '+' || *q == delim)
|
||||
break;
|
||||
}
|
||||
|
||||
if (in4_pton(p, end - p,
|
||||
if (in4_pton(p, q - p,
|
||||
(u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3],
|
||||
tdelim, &p)) {
|
||||
-1, &stop)) {
|
||||
srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
|
||||
srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
|
||||
srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
|
||||
} else if (in6_pton(p, end - p,
|
||||
} else if (in6_pton(p, q - p,
|
||||
srx->transport.sin6.sin6_addr.s6_addr,
|
||||
tdelim, &p)) {
|
||||
-1, &stop)) {
|
||||
/* Nothing to do */
|
||||
} else {
|
||||
goto bad_address;
|
||||
}
|
||||
|
||||
if (tdelim == ']') {
|
||||
if (p == end || *p != ']')
|
||||
goto bad_address;
|
||||
if (stop != q)
|
||||
goto bad_address;
|
||||
|
||||
p = q;
|
||||
if (q < end && *q == ']')
|
||||
p++;
|
||||
}
|
||||
|
||||
if (p < end) {
|
||||
if (*p == '+') {
|
||||
|
|
|
@ -23,36 +23,55 @@
|
|||
/*
|
||||
* Set up an interest-in-callbacks record for a volume on a server and
|
||||
* register it with the server.
|
||||
* - Called with volume->server_sem held.
|
||||
* - Called with vnode->io_lock held.
|
||||
*/
|
||||
int afs_register_server_cb_interest(struct afs_vnode *vnode,
|
||||
struct afs_server_entry *entry)
|
||||
struct afs_server_list *slist,
|
||||
unsigned int index)
|
||||
{
|
||||
struct afs_cb_interest *cbi = entry->cb_interest, *vcbi, *new, *x;
|
||||
struct afs_server_entry *entry = &slist->servers[index];
|
||||
struct afs_cb_interest *cbi, *vcbi, *new, *old;
|
||||
struct afs_server *server = entry->server;
|
||||
|
||||
again:
|
||||
if (vnode->cb_interest &&
|
||||
likely(vnode->cb_interest == entry->cb_interest))
|
||||
return 0;
|
||||
|
||||
read_lock(&slist->lock);
|
||||
cbi = afs_get_cb_interest(entry->cb_interest);
|
||||
read_unlock(&slist->lock);
|
||||
|
||||
vcbi = vnode->cb_interest;
|
||||
if (vcbi) {
|
||||
if (vcbi == cbi)
|
||||
return 0;
|
||||
|
||||
if (cbi && vcbi->server == cbi->server) {
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
vnode->cb_interest = afs_get_cb_interest(cbi);
|
||||
write_sequnlock(&vnode->cb_lock);
|
||||
if (vcbi == cbi) {
|
||||
afs_put_cb_interest(afs_v2net(vnode), cbi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use a new interest in the server list for the same server
|
||||
* rather than an old one that's still attached to a vnode.
|
||||
*/
|
||||
if (cbi && vcbi->server == cbi->server) {
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
old = vnode->cb_interest;
|
||||
vnode->cb_interest = cbi;
|
||||
write_sequnlock(&vnode->cb_lock);
|
||||
afs_put_cb_interest(afs_v2net(vnode), old);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Re-use the one attached to the vnode. */
|
||||
if (!cbi && vcbi->server == server) {
|
||||
afs_get_cb_interest(vcbi);
|
||||
x = cmpxchg(&entry->cb_interest, cbi, vcbi);
|
||||
if (x != cbi) {
|
||||
cbi = x;
|
||||
afs_put_cb_interest(afs_v2net(vnode), vcbi);
|
||||
write_lock(&slist->lock);
|
||||
if (entry->cb_interest) {
|
||||
write_unlock(&slist->lock);
|
||||
afs_put_cb_interest(afs_v2net(vnode), cbi);
|
||||
goto again;
|
||||
}
|
||||
|
||||
entry->cb_interest = cbi;
|
||||
write_unlock(&slist->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -72,13 +91,16 @@ int afs_register_server_cb_interest(struct afs_vnode *vnode,
|
|||
list_add_tail(&new->cb_link, &server->cb_interests);
|
||||
write_unlock(&server->cb_break_lock);
|
||||
|
||||
x = cmpxchg(&entry->cb_interest, cbi, new);
|
||||
if (x == cbi) {
|
||||
write_lock(&slist->lock);
|
||||
if (!entry->cb_interest) {
|
||||
entry->cb_interest = afs_get_cb_interest(new);
|
||||
cbi = new;
|
||||
new = NULL;
|
||||
} else {
|
||||
cbi = x;
|
||||
afs_put_cb_interest(afs_v2net(vnode), new);
|
||||
cbi = afs_get_cb_interest(entry->cb_interest);
|
||||
}
|
||||
write_unlock(&slist->lock);
|
||||
afs_put_cb_interest(afs_v2net(vnode), new);
|
||||
}
|
||||
|
||||
ASSERT(cbi);
|
||||
|
@ -88,11 +110,14 @@ int afs_register_server_cb_interest(struct afs_vnode *vnode,
|
|||
*/
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
|
||||
vnode->cb_interest = afs_get_cb_interest(cbi);
|
||||
old = vnode->cb_interest;
|
||||
vnode->cb_interest = cbi;
|
||||
vnode->cb_s_break = cbi->server->cb_s_break;
|
||||
vnode->cb_v_break = vnode->volume->cb_v_break;
|
||||
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
||||
|
||||
write_sequnlock(&vnode->cb_lock);
|
||||
afs_put_cb_interest(afs_v2net(vnode), old);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -171,13 +196,24 @@ static void afs_break_one_callback(struct afs_server *server,
|
|||
if (cbi->vid != fid->vid)
|
||||
continue;
|
||||
|
||||
data.volume = NULL;
|
||||
data.fid = *fid;
|
||||
inode = ilookup5_nowait(cbi->sb, fid->vnode, afs_iget5_test, &data);
|
||||
if (inode) {
|
||||
vnode = AFS_FS_I(inode);
|
||||
afs_break_callback(vnode);
|
||||
iput(inode);
|
||||
if (fid->vnode == 0 && fid->unique == 0) {
|
||||
/* The callback break applies to an entire volume. */
|
||||
struct afs_super_info *as = AFS_FS_S(cbi->sb);
|
||||
struct afs_volume *volume = as->volume;
|
||||
|
||||
write_lock(&volume->cb_break_lock);
|
||||
volume->cb_v_break++;
|
||||
write_unlock(&volume->cb_break_lock);
|
||||
} else {
|
||||
data.volume = NULL;
|
||||
data.fid = *fid;
|
||||
inode = ilookup5_nowait(cbi->sb, fid->vnode,
|
||||
afs_iget5_test, &data);
|
||||
if (inode) {
|
||||
vnode = AFS_FS_I(inode);
|
||||
afs_break_callback(vnode);
|
||||
iput(inode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +231,8 @@ void afs_break_callbacks(struct afs_server *server, size_t count,
|
|||
ASSERT(server != NULL);
|
||||
ASSERTCMP(count, <=, AFSCBMAX);
|
||||
|
||||
/* 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 }",
|
||||
callbacks->fid.vid,
|
||||
|
|
|
@ -133,21 +133,10 @@ bool afs_cm_incoming_call(struct afs_call *call)
|
|||
}
|
||||
|
||||
/*
|
||||
* clean up a cache manager call
|
||||
* Clean up a cache manager call.
|
||||
*/
|
||||
static void afs_cm_destructor(struct afs_call *call)
|
||||
{
|
||||
_enter("");
|
||||
|
||||
/* Break the callbacks here so that we do it after the final ACK is
|
||||
* received. The step number here must match the final number in
|
||||
* afs_deliver_cb_callback().
|
||||
*/
|
||||
if (call->unmarshall == 5) {
|
||||
ASSERT(call->cm_server && call->count && call->request);
|
||||
afs_break_callbacks(call->cm_server, call->count, call->request);
|
||||
}
|
||||
|
||||
kfree(call->buffer);
|
||||
call->buffer = NULL;
|
||||
}
|
||||
|
@ -161,14 +150,14 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
|
|||
|
||||
_enter("");
|
||||
|
||||
/* be sure to send the reply *before* attempting to spam the AFS server
|
||||
* with FSFetchStatus requests on the vnodes with broken callbacks lest
|
||||
* the AFS server get into a vicious cycle of trying to break further
|
||||
* callbacks because it hadn't received completion of the CBCallBack op
|
||||
* yet */
|
||||
afs_send_empty_reply(call);
|
||||
/* We need to break the callbacks before sending the reply as the
|
||||
* server holds up change visibility till it receives our reply so as
|
||||
* to maintain cache coherency.
|
||||
*/
|
||||
if (call->cm_server)
|
||||
afs_break_callbacks(call->cm_server, call->count, call->request);
|
||||
|
||||
afs_break_callbacks(call->cm_server, call->count, call->request);
|
||||
afs_send_empty_reply(call);
|
||||
afs_put_call(call);
|
||||
_leave("");
|
||||
}
|
||||
|
@ -180,7 +169,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
|
|||
{
|
||||
struct afs_callback_break *cb;
|
||||
struct sockaddr_rxrpc srx;
|
||||
struct afs_server *server;
|
||||
__be32 *bp;
|
||||
int ret, loop;
|
||||
|
||||
|
@ -267,15 +255,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
|
|||
|
||||
call->offset = 0;
|
||||
call->unmarshall++;
|
||||
|
||||
/* Record that the message was unmarshalled successfully so
|
||||
* that the call destructor can know do the callback breaking
|
||||
* work, even if the final ACK isn't received.
|
||||
*
|
||||
* If the step number changes, then afs_cm_destructor() must be
|
||||
* updated also.
|
||||
*/
|
||||
call->unmarshall++;
|
||||
case 5:
|
||||
break;
|
||||
}
|
||||
|
@ -286,10 +265,9 @@ static int afs_deliver_cb_callback(struct afs_call *call)
|
|||
/* 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);
|
||||
server = afs_find_server(call->net, &srx);
|
||||
if (!server)
|
||||
return -ENOTCONN;
|
||||
call->cm_server = server;
|
||||
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);
|
||||
}
|
||||
|
@ -303,7 +281,8 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
|
|||
|
||||
_enter("{%p}", call->cm_server);
|
||||
|
||||
afs_init_callback_state(call->cm_server);
|
||||
if (call->cm_server)
|
||||
afs_init_callback_state(call->cm_server);
|
||||
afs_send_empty_reply(call);
|
||||
afs_put_call(call);
|
||||
_leave("");
|
||||
|
@ -315,7 +294,6 @@ 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;
|
||||
struct afs_server *server;
|
||||
int ret;
|
||||
|
||||
_enter("");
|
||||
|
@ -328,10 +306,9 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
|
|||
|
||||
/* we'll need the file server record as that tells us which set of
|
||||
* vnodes to operate upon */
|
||||
server = afs_find_server(call->net, &srx);
|
||||
if (!server)
|
||||
return -ENOTCONN;
|
||||
call->cm_server = server;
|
||||
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);
|
||||
}
|
||||
|
@ -341,8 +318,6 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
|
|||
*/
|
||||
static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
|
||||
{
|
||||
struct sockaddr_rxrpc srx;
|
||||
struct afs_server *server;
|
||||
struct afs_uuid *r;
|
||||
unsigned loop;
|
||||
__be32 *b;
|
||||
|
@ -398,11 +373,11 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
|
|||
|
||||
/* 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);
|
||||
server = afs_find_server(call->net, &srx);
|
||||
if (!server)
|
||||
return -ENOTCONN;
|
||||
call->cm_server = server;
|
||||
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);
|
||||
}
|
||||
|
|
56
fs/afs/dir.c
56
fs/afs/dir.c
|
@ -180,6 +180,7 @@ static int afs_dir_open(struct inode *inode, struct file *file)
|
|||
* get reclaimed during the iteration.
|
||||
*/
|
||||
static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
|
||||
__acquires(&dvnode->validate_lock)
|
||||
{
|
||||
struct afs_read *req;
|
||||
loff_t i_size;
|
||||
|
@ -261,18 +262,21 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
|
|||
/* If we're going to reload, we need to lock all the pages to prevent
|
||||
* races.
|
||||
*/
|
||||
ret = -ERESTARTSYS;
|
||||
if (down_read_killable(&dvnode->validate_lock) < 0)
|
||||
goto error;
|
||||
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
goto success;
|
||||
|
||||
up_read(&dvnode->validate_lock);
|
||||
if (down_write_killable(&dvnode->validate_lock) < 0)
|
||||
goto error;
|
||||
|
||||
if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
|
||||
ret = -ERESTARTSYS;
|
||||
for (i = 0; i < req->nr_pages; i++)
|
||||
if (lock_page_killable(req->pages[i]) < 0)
|
||||
goto error_unlock;
|
||||
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
goto success;
|
||||
|
||||
ret = afs_fetch_data(dvnode, key, req);
|
||||
if (ret < 0)
|
||||
goto error_unlock_all;
|
||||
goto error_unlock;
|
||||
|
||||
task_io_account_read(PAGE_SIZE * req->nr_pages);
|
||||
|
||||
|
@ -284,33 +288,26 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
|
|||
for (i = 0; i < req->nr_pages; i++)
|
||||
if (!afs_dir_check_page(dvnode, req->pages[i],
|
||||
req->actual_len))
|
||||
goto error_unlock_all;
|
||||
goto error_unlock;
|
||||
|
||||
// TODO: Trim excess pages
|
||||
|
||||
set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
|
||||
}
|
||||
|
||||
downgrade_write(&dvnode->validate_lock);
|
||||
success:
|
||||
i = req->nr_pages;
|
||||
while (i > 0)
|
||||
unlock_page(req->pages[--i]);
|
||||
return req;
|
||||
|
||||
error_unlock_all:
|
||||
i = req->nr_pages;
|
||||
error_unlock:
|
||||
while (i > 0)
|
||||
unlock_page(req->pages[--i]);
|
||||
up_write(&dvnode->validate_lock);
|
||||
error:
|
||||
afs_put_read(req);
|
||||
_leave(" = %d", ret);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
content_has_grown:
|
||||
i = req->nr_pages;
|
||||
while (i > 0)
|
||||
unlock_page(req->pages[--i]);
|
||||
up_write(&dvnode->validate_lock);
|
||||
afs_put_read(req);
|
||||
goto retry;
|
||||
}
|
||||
|
@ -473,6 +470,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
|
|||
}
|
||||
|
||||
out:
|
||||
up_read(&dvnode->validate_lock);
|
||||
afs_put_read(req);
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
|
@ -1143,7 +1141,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
|
||||
&newfid, &newstatus, &newcb);
|
||||
}
|
||||
|
@ -1213,7 +1211,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
afs_fs_remove(&fc, dentry->d_name.name, true,
|
||||
data_version);
|
||||
}
|
||||
|
@ -1316,7 +1314,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
afs_fs_remove(&fc, dentry->d_name.name, false,
|
||||
data_version);
|
||||
}
|
||||
|
@ -1373,7 +1371,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
|
||||
&newfid, &newstatus, &newcb);
|
||||
}
|
||||
|
@ -1443,8 +1441,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
|||
}
|
||||
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
|
||||
fc.cb_break_2 = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_link(&fc, vnode, dentry->d_name.name, data_version);
|
||||
}
|
||||
|
||||
|
@ -1512,7 +1510,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
afs_fs_symlink(&fc, dentry->d_name.name,
|
||||
content, data_version,
|
||||
&newfid, &newstatus);
|
||||
|
@ -1588,8 +1586,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
}
|
||||
}
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = orig_dvnode->cb_break + orig_dvnode->cb_s_break;
|
||||
fc.cb_break_2 = new_dvnode->cb_break + new_dvnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
|
||||
fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
|
||||
afs_fs_rename(&fc, old_dentry->d_name.name,
|
||||
new_dvnode, new_dentry->d_name.name,
|
||||
orig_data_version, new_data_version);
|
||||
|
|
|
@ -238,7 +238,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, vnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_fetch_data(&fc, desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key,
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, vnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_set_lock(&fc, type);
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key)
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, vnode, key)) {
|
||||
while (afs_select_current_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_extend_lock(&fc);
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ static int afs_release_lock(struct afs_vnode *vnode, struct key *key)
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, vnode, key)) {
|
||||
while (afs_select_current_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_release_lock(&fc);
|
||||
}
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
|
|||
struct afs_read *read_req)
|
||||
{
|
||||
const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
|
||||
bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
|
||||
u64 data_version, size;
|
||||
u32 type, abort_code;
|
||||
u8 flags = 0;
|
||||
|
@ -142,13 +143,32 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
|
|||
if (vnode)
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
|
||||
abort_code = ntohl(xdr->abort_code);
|
||||
|
||||
if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
|
||||
if (xdr->if_version == htonl(0) &&
|
||||
abort_code != 0 &&
|
||||
inline_error) {
|
||||
/* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
|
||||
* whereby it doesn't set the interface version in the error
|
||||
* case.
|
||||
*/
|
||||
status->abort_code = abort_code;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (abort_code != 0 && inline_error) {
|
||||
status->abort_code = abort_code;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
type = ntohl(xdr->type);
|
||||
abort_code = ntohl(xdr->abort_code);
|
||||
switch (type) {
|
||||
case AFS_FTYPE_FILE:
|
||||
case AFS_FTYPE_DIR:
|
||||
|
@ -165,13 +185,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
|
|||
}
|
||||
status->type = type;
|
||||
break;
|
||||
case AFS_FTYPE_INVALID:
|
||||
if (abort_code != 0) {
|
||||
status->abort_code = abort_code;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
|
@ -248,7 +261,7 @@ static void xdr_decode_AFSCallBack(struct afs_call *call,
|
|||
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
|
||||
if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) {
|
||||
if (call->cb_break == afs_cb_break_sum(vnode, cbi)) {
|
||||
vnode->cb_version = ntohl(*bp++);
|
||||
cb_expiry = ntohl(*bp++);
|
||||
vnode->cb_type = ntohl(*bp++);
|
||||
|
|
|
@ -108,7 +108,7 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, vnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_fetch_file_status(&fc, NULL, new_inode);
|
||||
}
|
||||
|
||||
|
@ -393,15 +393,18 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
|
|||
read_seqlock_excl(&vnode->cb_lock);
|
||||
|
||||
if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
|
||||
if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break) {
|
||||
if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break ||
|
||||
vnode->cb_v_break != vnode->volume->cb_v_break) {
|
||||
vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
|
||||
vnode->cb_v_break = vnode->volume->cb_v_break;
|
||||
valid = false;
|
||||
} else if (vnode->status.type == AFS_FTYPE_DIR &&
|
||||
test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) &&
|
||||
vnode->cb_expires_at - 10 > now) {
|
||||
valid = true;
|
||||
valid = true;
|
||||
} else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
|
||||
vnode->cb_expires_at - 10 > now) {
|
||||
valid = true;
|
||||
valid = true;
|
||||
}
|
||||
} else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
|
||||
valid = true;
|
||||
|
@ -415,7 +418,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
|
|||
if (valid)
|
||||
goto valid;
|
||||
|
||||
mutex_lock(&vnode->validate_lock);
|
||||
down_write(&vnode->validate_lock);
|
||||
|
||||
/* if the promise has expired, we need to check the server again to get
|
||||
* a new promise - note that if the (parent) directory's metadata was
|
||||
|
@ -444,13 +447,13 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
|
|||
* different */
|
||||
if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
|
||||
afs_zap_data(vnode);
|
||||
mutex_unlock(&vnode->validate_lock);
|
||||
up_write(&vnode->validate_lock);
|
||||
valid:
|
||||
_leave(" = 0");
|
||||
return 0;
|
||||
|
||||
error_unlock:
|
||||
mutex_unlock(&vnode->validate_lock);
|
||||
up_write(&vnode->validate_lock);
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -574,7 +577,7 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, vnode, key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_setattr(&fc, attr);
|
||||
}
|
||||
|
||||
|
|
|
@ -396,6 +396,7 @@ struct afs_server {
|
|||
#define AFS_SERVER_FL_PROBED 5 /* The fileserver has been probed */
|
||||
#define AFS_SERVER_FL_PROBING 6 /* Fileserver is being probed */
|
||||
#define AFS_SERVER_FL_NO_IBULK 7 /* Fileserver doesn't support FS.InlineBulkStatus */
|
||||
#define AFS_SERVER_FL_MAY_HAVE_CB 8 /* May have callbacks on this fileserver */
|
||||
atomic_t usage;
|
||||
u32 addr_version; /* Address list version */
|
||||
|
||||
|
@ -433,6 +434,7 @@ struct afs_server_list {
|
|||
unsigned short index; /* Server currently in use */
|
||||
unsigned short vnovol_mask; /* Servers to be skipped due to VNOVOL */
|
||||
unsigned int seq; /* Set to ->servers_seq when installed */
|
||||
rwlock_t lock;
|
||||
struct afs_server_entry servers[];
|
||||
};
|
||||
|
||||
|
@ -459,6 +461,9 @@ struct afs_volume {
|
|||
rwlock_t servers_lock; /* Lock for ->servers */
|
||||
unsigned int servers_seq; /* Incremented each time ->servers changes */
|
||||
|
||||
unsigned cb_v_break; /* Break-everything counter. */
|
||||
rwlock_t cb_break_lock;
|
||||
|
||||
afs_voltype_t type; /* type of volume */
|
||||
short error;
|
||||
char type_force; /* force volume type (suppress R/O -> R/W) */
|
||||
|
@ -494,7 +499,7 @@ struct afs_vnode {
|
|||
#endif
|
||||
struct afs_permits __rcu *permit_cache; /* cache of permits so far obtained */
|
||||
struct mutex io_lock; /* Lock for serialising I/O on this mutex */
|
||||
struct mutex validate_lock; /* lock for validating this vnode */
|
||||
struct rw_semaphore validate_lock; /* lock for validating this vnode */
|
||||
spinlock_t wb_lock; /* lock for wb_keys */
|
||||
spinlock_t lock; /* waitqueue/flags lock */
|
||||
unsigned long flags;
|
||||
|
@ -519,6 +524,7 @@ struct afs_vnode {
|
|||
/* outstanding callback notification on this file */
|
||||
struct afs_cb_interest *cb_interest; /* Server on which this resides */
|
||||
unsigned int cb_s_break; /* Mass break counter on ->server */
|
||||
unsigned int cb_v_break; /* Mass break counter on ->volume */
|
||||
unsigned int cb_break; /* Break counter on vnode */
|
||||
seqlock_t cb_lock; /* Lock for ->cb_interest, ->status, ->cb_*break */
|
||||
|
||||
|
@ -648,16 +654,29 @@ extern void afs_init_callback_state(struct afs_server *);
|
|||
extern void afs_break_callback(struct afs_vnode *);
|
||||
extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*);
|
||||
|
||||
extern int afs_register_server_cb_interest(struct afs_vnode *, struct afs_server_entry *);
|
||||
extern int afs_register_server_cb_interest(struct afs_vnode *,
|
||||
struct afs_server_list *, unsigned int);
|
||||
extern void afs_put_cb_interest(struct afs_net *, struct afs_cb_interest *);
|
||||
extern void afs_clear_callback_interests(struct afs_net *, struct afs_server_list *);
|
||||
|
||||
static inline struct afs_cb_interest *afs_get_cb_interest(struct afs_cb_interest *cbi)
|
||||
{
|
||||
refcount_inc(&cbi->usage);
|
||||
if (cbi)
|
||||
refcount_inc(&cbi->usage);
|
||||
return cbi;
|
||||
}
|
||||
|
||||
static inline unsigned int afs_calc_vnode_cb_break(struct afs_vnode *vnode)
|
||||
{
|
||||
return vnode->cb_break + vnode->cb_s_break + vnode->cb_v_break;
|
||||
}
|
||||
|
||||
static inline unsigned int afs_cb_break_sum(struct afs_vnode *vnode,
|
||||
struct afs_cb_interest *cbi)
|
||||
{
|
||||
return vnode->cb_break + cbi->server->cb_s_break + vnode->volume->cb_v_break;
|
||||
}
|
||||
|
||||
/*
|
||||
* cell.c
|
||||
*/
|
||||
|
|
|
@ -179,7 +179,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
|
|||
*/
|
||||
if (fc->flags & AFS_FS_CURSOR_VNOVOL) {
|
||||
fc->ac.error = -EREMOTEIO;
|
||||
goto failed;
|
||||
goto next_server;
|
||||
}
|
||||
|
||||
write_lock(&vnode->volume->servers_lock);
|
||||
|
@ -201,7 +201,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
|
|||
*/
|
||||
if (vnode->volume->servers == fc->server_list) {
|
||||
fc->ac.error = -EREMOTEIO;
|
||||
goto failed;
|
||||
goto next_server;
|
||||
}
|
||||
|
||||
/* Try again */
|
||||
|
@ -350,8 +350,8 @@ 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->servers[fc->index]);
|
||||
fc->ac.error = afs_register_server_cb_interest(vnode, fc->server_list,
|
||||
fc->index);
|
||||
if (fc->ac.error < 0)
|
||||
goto failed;
|
||||
|
||||
|
@ -369,8 +369,16 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
|
|||
if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) {
|
||||
fc->ac.alist = afs_get_addrlist(alist);
|
||||
|
||||
if (!afs_probe_fileserver(fc))
|
||||
goto failed;
|
||||
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)
|
||||
|
|
|
@ -41,6 +41,7 @@ int afs_open_socket(struct afs_net *net)
|
|||
{
|
||||
struct sockaddr_rxrpc srx;
|
||||
struct socket *socket;
|
||||
unsigned int min_level;
|
||||
int ret;
|
||||
|
||||
_enter("");
|
||||
|
@ -60,6 +61,12 @@ int afs_open_socket(struct afs_net *net)
|
|||
srx.transport.sin6.sin6_family = AF_INET6;
|
||||
srx.transport.sin6.sin6_port = htons(AFS_CM_PORT);
|
||||
|
||||
min_level = RXRPC_SECURITY_ENCRYPT;
|
||||
ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL,
|
||||
(void *)&min_level, sizeof(min_level));
|
||||
if (ret < 0)
|
||||
goto error_2;
|
||||
|
||||
ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
|
||||
if (ret == -EADDRINUSE) {
|
||||
srx.transport.sin6.sin6_port = 0;
|
||||
|
@ -482,8 +489,12 @@ static void afs_deliver_to_call(struct afs_call *call)
|
|||
state = READ_ONCE(call->state);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
if (state == AFS_CALL_CL_PROC_REPLY)
|
||||
if (state == AFS_CALL_CL_PROC_REPLY) {
|
||||
if (call->cbi)
|
||||
set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
|
||||
&call->cbi->server->flags);
|
||||
goto call_complete;
|
||||
}
|
||||
ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
|
||||
goto done;
|
||||
case -EINPROGRESS:
|
||||
|
@ -493,11 +504,6 @@ static void afs_deliver_to_call(struct afs_call *call)
|
|||
case -ECONNABORTED:
|
||||
ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
|
||||
goto done;
|
||||
case -ENOTCONN:
|
||||
abort_code = RX_CALL_DEAD;
|
||||
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
|
||||
abort_code, ret, "KNC");
|
||||
goto local_abort;
|
||||
case -ENOTSUPP:
|
||||
abort_code = RXGEN_OPCODE;
|
||||
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
|
||||
|
|
|
@ -147,8 +147,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
|
|||
break;
|
||||
}
|
||||
|
||||
if (cb_break != (vnode->cb_break +
|
||||
vnode->cb_interest->server->cb_s_break)) {
|
||||
if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest)) {
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
|
@ -178,7 +177,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
|
|||
}
|
||||
}
|
||||
|
||||
if (cb_break != (vnode->cb_break + vnode->cb_interest->server->cb_s_break))
|
||||
if (cb_break != afs_cb_break_sum(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
|
||||
|
@ -257,7 +256,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 == (vnode->cb_break + vnode->cb_interest->server->cb_s_break) &&
|
||||
if (cb_break == afs_cb_break_sum(vnode, vnode->cb_interest) &&
|
||||
zap == permits)
|
||||
rcu_assign_pointer(vnode->permit_cache, replacement);
|
||||
else
|
||||
|
|
|
@ -67,12 +67,6 @@ struct afs_server *afs_find_server(struct afs_net *net,
|
|||
sizeof(struct in6_addr));
|
||||
if (diff == 0)
|
||||
goto found;
|
||||
if (diff < 0) {
|
||||
// TODO: Sort the list
|
||||
//if (i == alist->nr_ipv4)
|
||||
// goto not_found;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -87,17 +81,10 @@ struct afs_server *afs_find_server(struct afs_net *net,
|
|||
(u32 __force)b->sin6_addr.s6_addr32[3]);
|
||||
if (diff == 0)
|
||||
goto found;
|
||||
if (diff < 0) {
|
||||
// TODO: Sort the list
|
||||
//if (i == 0)
|
||||
// goto not_found;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//not_found:
|
||||
server = NULL;
|
||||
found:
|
||||
if (server && !atomic_inc_not_zero(&server->usage))
|
||||
|
@ -395,14 +382,16 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
|
|||
struct afs_addr_list *alist = rcu_access_pointer(server->addresses);
|
||||
struct afs_addr_cursor ac = {
|
||||
.alist = alist,
|
||||
.addr = &alist->addrs[0],
|
||||
.start = alist->index,
|
||||
.index = alist->index,
|
||||
.index = 0,
|
||||
.addr = &alist->addrs[alist->index],
|
||||
.error = 0,
|
||||
};
|
||||
_enter("%p", server);
|
||||
|
||||
afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
|
||||
if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
|
||||
afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
|
||||
|
||||
call_rcu(&server->rcu, afs_server_rcu);
|
||||
afs_dec_servers_outstanding(net);
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
|
|||
goto error;
|
||||
|
||||
refcount_set(&slist->usage, 1);
|
||||
rwlock_init(&slist->lock);
|
||||
|
||||
/* Make sure a records exists for each server in the list. */
|
||||
for (i = 0; i < vldb->nr_servers; i++) {
|
||||
|
@ -64,9 +65,11 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
|
|||
goto error_2;
|
||||
}
|
||||
|
||||
/* Insertion-sort by server pointer */
|
||||
/* Insertion-sort by UUID */
|
||||
for (j = 0; j < slist->nr_servers; j++)
|
||||
if (slist->servers[j].server >= server)
|
||||
if (memcmp(&slist->servers[j].server->uuid,
|
||||
&server->uuid,
|
||||
sizeof(server->uuid)) >= 0)
|
||||
break;
|
||||
if (j < slist->nr_servers) {
|
||||
if (slist->servers[j].server == server) {
|
||||
|
|
|
@ -590,7 +590,7 @@ static void afs_i_init_once(void *_vnode)
|
|||
memset(vnode, 0, sizeof(*vnode));
|
||||
inode_init_once(&vnode->vfs_inode);
|
||||
mutex_init(&vnode->io_lock);
|
||||
mutex_init(&vnode->validate_lock);
|
||||
init_rwsem(&vnode->validate_lock);
|
||||
spin_lock_init(&vnode->wb_lock);
|
||||
spin_lock_init(&vnode->lock);
|
||||
INIT_LIST_HEAD(&vnode->wb_keys);
|
||||
|
@ -688,7 +688,7 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
if (afs_begin_vnode_operation(&fc, vnode, key)) {
|
||||
fc.flags |= AFS_FS_CURSOR_NO_VSLEEP;
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_get_volume_status(&fc, &vs);
|
||||
}
|
||||
|
||||
|
|
|
@ -351,7 +351,7 @@ static int afs_store_data(struct address_space *mapping,
|
|||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, vnode, wbk->key)) {
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = vnode->cb_break + vnode->cb_s_break;
|
||||
fc.cb_break = afs_calc_vnode_cb_break(vnode);
|
||||
afs_fs_store_data(&fc, mapping, first, last, offset, to);
|
||||
}
|
||||
|
||||
|
|
|
@ -575,6 +575,48 @@ TRACE_EVENT(afs_protocol_error,
|
|||
__entry->call, __entry->error, __entry->where)
|
||||
);
|
||||
|
||||
TRACE_EVENT(afs_cm_no_server,
|
||||
TP_PROTO(struct afs_call *call, struct sockaddr_rxrpc *srx),
|
||||
|
||||
TP_ARGS(call, srx),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, call )
|
||||
__field(unsigned int, op_id )
|
||||
__field_struct(struct sockaddr_rxrpc, srx )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->call = call->debug_id;
|
||||
__entry->op_id = call->operation_ID;
|
||||
memcpy(&__entry->srx, srx, sizeof(__entry->srx));
|
||||
),
|
||||
|
||||
TP_printk("c=%08x op=%u %pISpc",
|
||||
__entry->call, __entry->op_id, &__entry->srx.transport)
|
||||
);
|
||||
|
||||
TRACE_EVENT(afs_cm_no_server_u,
|
||||
TP_PROTO(struct afs_call *call, const uuid_t *uuid),
|
||||
|
||||
TP_ARGS(call, uuid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, call )
|
||||
__field(unsigned int, op_id )
|
||||
__field_struct(uuid_t, uuid )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->call = call->debug_id;
|
||||
__entry->op_id = call->operation_ID;
|
||||
memcpy(&__entry->uuid, uuid, sizeof(__entry->uuid));
|
||||
),
|
||||
|
||||
TP_printk("c=%08x op=%u %pU",
|
||||
__entry->call, __entry->op_id, &__entry->uuid)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_AFS_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
|
Loading…
Reference in New Issue