Commit aaa9c107 authored by David S. Miller's avatar David S. Miller

Merge tag 'rxrpc-rewrite-20170109' of...

Merge tag 'rxrpc-rewrite-20170109' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

David Howells says:

====================
afs: Refcount afs_call struct

These patches provide some tracepoints for AFS and fix a potential leak by
adding refcounting to the afs_call struct.

The patches are:

 (1) Add some tracepoints for logging incoming calls and monitoring
     notifications from AF_RXRPC and data reception.

 (2) Get rid of afs_wait_mode as it didn't turn out to be as useful as
     initially expected.  It can be brought back later if needed.  This
     clears some stuff out that I don't then need to fix up in (4).

 (3) Allow listen(..., 0) to be used to disable listening.  This makes
     shutting down the AFS cache manager server in the kernel much easier
     and the accounting simpler as we can then be sure that (a) all
     preallocated afs_call structs are relesed and (b) no new incoming
     calls are going to be started.

     For the moment, listening cannot be reenabled.

 (4) Add refcounting to the afs_call struct to fix a potential multiple
     release detected by static checking and add a tracepoint to follow the
     lifecycle of afs_call objects.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 73517885 341f741f
...@@ -343,7 +343,7 @@ void afs_dispatch_give_up_callbacks(struct work_struct *work) ...@@ -343,7 +343,7 @@ void afs_dispatch_give_up_callbacks(struct work_struct *work)
* had callbacks entirely, and the server will call us later to break * had callbacks entirely, and the server will call us later to break
* them * them
*/ */
afs_fs_give_up_callbacks(server, &afs_async_call); afs_fs_give_up_callbacks(server, true);
} }
/* /*
......
...@@ -24,65 +24,86 @@ static int afs_deliver_cb_callback(struct afs_call *); ...@@ -24,65 +24,86 @@ static int afs_deliver_cb_callback(struct afs_call *);
static int afs_deliver_cb_probe_uuid(struct afs_call *); static int afs_deliver_cb_probe_uuid(struct afs_call *);
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *); static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *);
static void afs_cm_destructor(struct afs_call *); static void afs_cm_destructor(struct afs_call *);
static void SRXAFSCB_CallBack(struct work_struct *);
static void SRXAFSCB_InitCallBackState(struct work_struct *);
static void SRXAFSCB_Probe(struct work_struct *);
static void SRXAFSCB_ProbeUuid(struct work_struct *);
static void SRXAFSCB_TellMeAboutYourself(struct work_struct *);
#define CM_NAME(name) \
const char afs_SRXCB##name##_name[] __tracepoint_string = \
"CB." #name
/* /*
* CB.CallBack operation type * CB.CallBack operation type
*/ */
static CM_NAME(CallBack);
static const struct afs_call_type afs_SRXCBCallBack = { static const struct afs_call_type afs_SRXCBCallBack = {
.name = "CB.CallBack", .name = afs_SRXCBCallBack_name,
.deliver = afs_deliver_cb_callback, .deliver = afs_deliver_cb_callback,
.abort_to_error = afs_abort_to_error, .abort_to_error = afs_abort_to_error,
.destructor = afs_cm_destructor, .destructor = afs_cm_destructor,
.work = SRXAFSCB_CallBack,
}; };
/* /*
* CB.InitCallBackState operation type * CB.InitCallBackState operation type
*/ */
static CM_NAME(InitCallBackState);
static const struct afs_call_type afs_SRXCBInitCallBackState = { static const struct afs_call_type afs_SRXCBInitCallBackState = {
.name = "CB.InitCallBackState", .name = afs_SRXCBInitCallBackState_name,
.deliver = afs_deliver_cb_init_call_back_state, .deliver = afs_deliver_cb_init_call_back_state,
.abort_to_error = afs_abort_to_error, .abort_to_error = afs_abort_to_error,
.destructor = afs_cm_destructor, .destructor = afs_cm_destructor,
.work = SRXAFSCB_InitCallBackState,
}; };
/* /*
* CB.InitCallBackState3 operation type * CB.InitCallBackState3 operation type
*/ */
static CM_NAME(InitCallBackState3);
static const struct afs_call_type afs_SRXCBInitCallBackState3 = { static const struct afs_call_type afs_SRXCBInitCallBackState3 = {
.name = "CB.InitCallBackState3", .name = afs_SRXCBInitCallBackState3_name,
.deliver = afs_deliver_cb_init_call_back_state3, .deliver = afs_deliver_cb_init_call_back_state3,
.abort_to_error = afs_abort_to_error, .abort_to_error = afs_abort_to_error,
.destructor = afs_cm_destructor, .destructor = afs_cm_destructor,
.work = SRXAFSCB_InitCallBackState,
}; };
/* /*
* CB.Probe operation type * CB.Probe operation type
*/ */
static CM_NAME(Probe);
static const struct afs_call_type afs_SRXCBProbe = { static const struct afs_call_type afs_SRXCBProbe = {
.name = "CB.Probe", .name = afs_SRXCBProbe_name,
.deliver = afs_deliver_cb_probe, .deliver = afs_deliver_cb_probe,
.abort_to_error = afs_abort_to_error, .abort_to_error = afs_abort_to_error,
.destructor = afs_cm_destructor, .destructor = afs_cm_destructor,
.work = SRXAFSCB_Probe,
}; };
/* /*
* CB.ProbeUuid operation type * CB.ProbeUuid operation type
*/ */
static CM_NAME(ProbeUuid);
static const struct afs_call_type afs_SRXCBProbeUuid = { static const struct afs_call_type afs_SRXCBProbeUuid = {
.name = "CB.ProbeUuid", .name = afs_SRXCBProbeUuid_name,
.deliver = afs_deliver_cb_probe_uuid, .deliver = afs_deliver_cb_probe_uuid,
.abort_to_error = afs_abort_to_error, .abort_to_error = afs_abort_to_error,
.destructor = afs_cm_destructor, .destructor = afs_cm_destructor,
.work = SRXAFSCB_ProbeUuid,
}; };
/* /*
* CB.TellMeAboutYourself operation type * CB.TellMeAboutYourself operation type
*/ */
static CM_NAME(TellMeAboutYourself);
static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
.name = "CB.TellMeAboutYourself", .name = afs_SRXCBTellMeAboutYourself_name,
.deliver = afs_deliver_cb_tell_me_about_yourself, .deliver = afs_deliver_cb_tell_me_about_yourself,
.abort_to_error = afs_abort_to_error, .abort_to_error = afs_abort_to_error,
.destructor = afs_cm_destructor, .destructor = afs_cm_destructor,
.work = SRXAFSCB_TellMeAboutYourself,
}; };
/* /*
...@@ -153,6 +174,7 @@ static void SRXAFSCB_CallBack(struct work_struct *work) ...@@ -153,6 +174,7 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
afs_send_empty_reply(call); afs_send_empty_reply(call);
afs_break_callbacks(call->server, call->count, call->request); afs_break_callbacks(call->server, call->count, call->request);
afs_put_call(call);
_leave(""); _leave("");
} }
...@@ -274,9 +296,7 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -274,9 +296,7 @@ static int afs_deliver_cb_callback(struct afs_call *call)
return -ENOTCONN; return -ENOTCONN;
call->server = server; call->server = server;
INIT_WORK(&call->work, SRXAFSCB_CallBack); return afs_queue_call_work(call);
queue_work(afs_wq, &call->work);
return 0;
} }
/* /*
...@@ -290,6 +310,7 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work) ...@@ -290,6 +310,7 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
afs_init_callback_state(call->server); afs_init_callback_state(call->server);
afs_send_empty_reply(call); afs_send_empty_reply(call);
afs_put_call(call);
_leave(""); _leave("");
} }
...@@ -320,9 +341,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call) ...@@ -320,9 +341,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
return -ENOTCONN; return -ENOTCONN;
call->server = server; call->server = server;
INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); return afs_queue_call_work(call);
queue_work(afs_wq, &call->work);
return 0;
} }
/* /*
...@@ -394,9 +413,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) ...@@ -394,9 +413,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
return -ENOTCONN; return -ENOTCONN;
call->server = server; call->server = server;
INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); return afs_queue_call_work(call);
queue_work(afs_wq, &call->work);
return 0;
} }
/* /*
...@@ -408,6 +425,7 @@ static void SRXAFSCB_Probe(struct work_struct *work) ...@@ -408,6 +425,7 @@ static void SRXAFSCB_Probe(struct work_struct *work)
_enter(""); _enter("");
afs_send_empty_reply(call); afs_send_empty_reply(call);
afs_put_call(call);
_leave(""); _leave("");
} }
...@@ -427,9 +445,7 @@ static int afs_deliver_cb_probe(struct afs_call *call) ...@@ -427,9 +445,7 @@ static int afs_deliver_cb_probe(struct afs_call *call)
/* no unmarshalling required */ /* no unmarshalling required */
call->state = AFS_CALL_REPLYING; call->state = AFS_CALL_REPLYING;
INIT_WORK(&call->work, SRXAFSCB_Probe); return afs_queue_call_work(call);
queue_work(afs_wq, &call->work);
return 0;
} }
/* /*
...@@ -452,6 +468,7 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work) ...@@ -452,6 +468,7 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
reply.match = htonl(1); reply.match = htonl(1);
afs_send_simple_reply(call, &reply, sizeof(reply)); afs_send_simple_reply(call, &reply, sizeof(reply));
afs_put_call(call);
_leave(""); _leave("");
} }
...@@ -510,9 +527,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) ...@@ -510,9 +527,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
call->state = AFS_CALL_REPLYING; call->state = AFS_CALL_REPLYING;
INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); return afs_queue_call_work(call);
queue_work(afs_wq, &call->work);
return 0;
} }
/* /*
...@@ -574,7 +589,7 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) ...@@ -574,7 +589,7 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
reply.cap.capcount = htonl(1); reply.cap.capcount = htonl(1);
reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION); reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION);
afs_send_simple_reply(call, &reply, sizeof(reply)); afs_send_simple_reply(call, &reply, sizeof(reply));
afs_put_call(call);
_leave(""); _leave("");
} }
...@@ -594,7 +609,5 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call) ...@@ -594,7 +609,5 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
/* no unmarshalling required */ /* no unmarshalling required */
call->state = AFS_CALL_REPLYING; call->state = AFS_CALL_REPLYING;
INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself); return afs_queue_call_work(call);
queue_work(afs_wq, &call->work);
return 0;
} }
This diff is collapsed.
...@@ -51,31 +51,22 @@ struct afs_mount_params { ...@@ -51,31 +51,22 @@ struct afs_mount_params {
struct key *key; /* key to use for secure mounting */ struct key *key; /* key to use for secure mounting */
}; };
/* enum afs_call_state {
* definition of how to wait for the completion of an operation AFS_CALL_REQUESTING, /* request is being sent for outgoing call */
*/ AFS_CALL_AWAIT_REPLY, /* awaiting reply to outgoing call */
struct afs_wait_mode { AFS_CALL_AWAIT_OP_ID, /* awaiting op ID on incoming call */
/* RxRPC received message notification */ AFS_CALL_AWAIT_REQUEST, /* awaiting request data on incoming call */
rxrpc_notify_rx_t notify_rx; AFS_CALL_REPLYING, /* replying to incoming call */
AFS_CALL_AWAIT_ACK, /* awaiting final ACK of incoming call */
/* synchronous call waiter and call dispatched notification */ AFS_CALL_COMPLETE, /* Completed or failed */
int (*wait)(struct afs_call *call);
/* asynchronous call completion */
void (*async_complete)(void *reply, int error);
}; };
extern const struct afs_wait_mode afs_sync_call;
extern const struct afs_wait_mode afs_async_call;
/* /*
* a record of an in-progress RxRPC call * a record of an in-progress RxRPC call
*/ */
struct afs_call { struct afs_call {
const struct afs_call_type *type; /* type of call */ const struct afs_call_type *type; /* type of call */
const struct afs_wait_mode *wait_mode; /* completion wait mode */
wait_queue_head_t waitq; /* processes awaiting completion */ wait_queue_head_t waitq; /* processes awaiting completion */
struct work_struct async_work; /* asynchronous work processor */ struct work_struct async_work; /* async I/O processor */
struct work_struct work; /* actual work processor */ struct work_struct work; /* actual work processor */
struct rxrpc_call *rxcall; /* RxRPC call handle */ struct rxrpc_call *rxcall; /* RxRPC call handle */
struct key *key; /* security for this call */ struct key *key; /* security for this call */
...@@ -91,15 +82,8 @@ struct afs_call { ...@@ -91,15 +82,8 @@ struct afs_call {
pgoff_t first; /* first page in mapping to deal with */ pgoff_t first; /* first page in mapping to deal with */
pgoff_t last; /* last page in mapping to deal with */ pgoff_t last; /* last page in mapping to deal with */
size_t offset; /* offset into received data store */ size_t offset; /* offset into received data store */
enum { /* call state */ atomic_t usage;
AFS_CALL_REQUESTING, /* request is being sent for outgoing call */ enum afs_call_state state;
AFS_CALL_AWAIT_REPLY, /* awaiting reply to outgoing call */
AFS_CALL_AWAIT_OP_ID, /* awaiting op ID on incoming call */
AFS_CALL_AWAIT_REQUEST, /* awaiting request data on incoming call */
AFS_CALL_REPLYING, /* replying to incoming call */
AFS_CALL_AWAIT_ACK, /* awaiting final ACK of incoming call */
AFS_CALL_COMPLETE, /* Completed or failed */
} state;
int error; /* error code */ int error; /* error code */
u32 abort_code; /* Remote abort ID or 0 */ u32 abort_code; /* Remote abort ID or 0 */
unsigned request_size; /* size of request data */ unsigned request_size; /* size of request data */
...@@ -110,6 +94,7 @@ struct afs_call { ...@@ -110,6 +94,7 @@ struct afs_call {
bool incoming; /* T if incoming call */ bool incoming; /* T if incoming call */
bool send_pages; /* T if data from mapping should be sent */ bool send_pages; /* T if data from mapping should be sent */
bool need_attention; /* T if RxRPC poked us */ bool need_attention; /* T if RxRPC poked us */
bool async; /* T if asynchronous */
u16 service_id; /* RxRPC service ID to call */ u16 service_id; /* RxRPC service ID to call */
__be16 port; /* target UDP port */ __be16 port; /* target UDP port */
u32 operation_ID; /* operation ID for an incoming call */ u32 operation_ID; /* operation ID for an incoming call */
...@@ -131,6 +116,9 @@ struct afs_call_type { ...@@ -131,6 +116,9 @@ struct afs_call_type {
/* clean up a call */ /* clean up a call */
void (*destructor)(struct afs_call *call); void (*destructor)(struct afs_call *call);
/* Work function */
void (*work)(struct work_struct *work);
}; };
/* /*
...@@ -526,50 +514,37 @@ extern int afs_flock(struct file *, int, struct file_lock *); ...@@ -526,50 +514,37 @@ extern int afs_flock(struct file *, int, struct file_lock *);
*/ */
extern int afs_fs_fetch_file_status(struct afs_server *, struct key *, extern int afs_fs_fetch_file_status(struct afs_server *, struct key *,
struct afs_vnode *, struct afs_volsync *, struct afs_vnode *, struct afs_volsync *,
const struct afs_wait_mode *); bool);
extern int afs_fs_give_up_callbacks(struct afs_server *, extern int afs_fs_give_up_callbacks(struct afs_server *, bool);
const struct afs_wait_mode *);
extern int afs_fs_fetch_data(struct afs_server *, struct key *, extern int afs_fs_fetch_data(struct afs_server *, struct key *,
struct afs_vnode *, struct afs_read *, struct afs_vnode *, struct afs_read *, bool);
const struct afs_wait_mode *);
extern int afs_fs_create(struct afs_server *, struct key *, extern int afs_fs_create(struct afs_server *, struct key *,
struct afs_vnode *, const char *, umode_t, struct afs_vnode *, const char *, umode_t,
struct afs_fid *, struct afs_file_status *, struct afs_fid *, struct afs_file_status *,
struct afs_callback *, struct afs_callback *, bool);
const struct afs_wait_mode *);
extern int afs_fs_remove(struct afs_server *, struct key *, extern int afs_fs_remove(struct afs_server *, struct key *,
struct afs_vnode *, const char *, bool, struct afs_vnode *, const char *, bool, bool);
const struct afs_wait_mode *);
extern int afs_fs_link(struct afs_server *, struct key *, struct afs_vnode *, extern int afs_fs_link(struct afs_server *, struct key *, struct afs_vnode *,
struct afs_vnode *, const char *, struct afs_vnode *, const char *, bool);
const struct afs_wait_mode *);
extern int afs_fs_symlink(struct afs_server *, struct key *, extern int afs_fs_symlink(struct afs_server *, struct key *,
struct afs_vnode *, const char *, const char *, struct afs_vnode *, const char *, const char *,
struct afs_fid *, struct afs_file_status *, struct afs_fid *, struct afs_file_status *, bool);
const struct afs_wait_mode *);
extern int afs_fs_rename(struct afs_server *, struct key *, extern int afs_fs_rename(struct afs_server *, struct key *,
struct afs_vnode *, const char *, struct afs_vnode *, const char *,
struct afs_vnode *, const char *, struct afs_vnode *, const char *, bool);
const struct afs_wait_mode *);
extern int afs_fs_store_data(struct afs_server *, struct afs_writeback *, extern int afs_fs_store_data(struct afs_server *, struct afs_writeback *,
pgoff_t, pgoff_t, unsigned, unsigned, pgoff_t, pgoff_t, unsigned, unsigned, bool);
const struct afs_wait_mode *);
extern int afs_fs_setattr(struct afs_server *, struct key *, extern int afs_fs_setattr(struct afs_server *, struct key *,
struct afs_vnode *, struct iattr *, struct afs_vnode *, struct iattr *, bool);
const struct afs_wait_mode *);
extern int afs_fs_get_volume_status(struct afs_server *, struct key *, extern int afs_fs_get_volume_status(struct afs_server *, struct key *,
struct afs_vnode *, struct afs_vnode *,
struct afs_volume_status *, struct afs_volume_status *, bool);
const struct afs_wait_mode *);
extern int afs_fs_set_lock(struct afs_server *, struct key *, extern int afs_fs_set_lock(struct afs_server *, struct key *,
struct afs_vnode *, afs_lock_type_t, struct afs_vnode *, afs_lock_type_t, bool);
const struct afs_wait_mode *);
extern int afs_fs_extend_lock(struct afs_server *, struct key *, extern int afs_fs_extend_lock(struct afs_server *, struct key *,
struct afs_vnode *, struct afs_vnode *, bool);
const struct afs_wait_mode *);
extern int afs_fs_release_lock(struct afs_server *, struct key *, extern int afs_fs_release_lock(struct afs_server *, struct key *,
struct afs_vnode *, struct afs_vnode *, bool);
const struct afs_wait_mode *);
/* /*
* inode.c * inode.c
...@@ -620,11 +595,13 @@ extern void afs_proc_cell_remove(struct afs_cell *); ...@@ -620,11 +595,13 @@ extern void afs_proc_cell_remove(struct afs_cell *);
* rxrpc.c * rxrpc.c
*/ */
extern struct socket *afs_socket; extern struct socket *afs_socket;
extern atomic_t afs_outstanding_calls;
extern int afs_open_socket(void); extern int afs_open_socket(void);
extern void afs_close_socket(void); extern void afs_close_socket(void);
extern int afs_make_call(struct in_addr *, struct afs_call *, gfp_t, extern void afs_put_call(struct afs_call *);
const struct afs_wait_mode *); extern int afs_queue_call_work(struct afs_call *);
extern int afs_make_call(struct in_addr *, struct afs_call *, gfp_t, bool);
extern struct afs_call *afs_alloc_flat_call(const struct afs_call_type *, extern struct afs_call *afs_alloc_flat_call(const struct afs_call_type *,
size_t, size_t); size_t, size_t);
extern void afs_flat_call_destructor(struct afs_call *); extern void afs_flat_call_destructor(struct afs_call *);
...@@ -680,11 +657,10 @@ extern int afs_get_MAC_address(u8 *, size_t); ...@@ -680,11 +657,10 @@ extern int afs_get_MAC_address(u8 *, size_t);
*/ */
extern int afs_vl_get_entry_by_name(struct in_addr *, struct key *, extern int afs_vl_get_entry_by_name(struct in_addr *, struct key *,
const char *, struct afs_cache_vlocation *, const char *, struct afs_cache_vlocation *,
const struct afs_wait_mode *); bool);
extern int afs_vl_get_entry_by_id(struct in_addr *, struct key *, extern int afs_vl_get_entry_by_id(struct in_addr *, struct key *,
afs_volid_t, afs_voltype_t, afs_volid_t, afs_voltype_t,
struct afs_cache_vlocation *, struct afs_cache_vlocation *, bool);
const struct afs_wait_mode *);
/* /*
* vlocation.c * vlocation.c
...@@ -773,6 +749,8 @@ extern int afs_fsync(struct file *, loff_t, loff_t, int); ...@@ -773,6 +749,8 @@ extern int afs_fsync(struct file *, loff_t, loff_t, int);
/* /*
* debug tracing * debug tracing
*/ */
#include <trace/events/afs.h>
extern unsigned afs_debug; extern unsigned afs_debug;
#define dbgprintk(FMT,...) \ #define dbgprintk(FMT,...) \
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/random.h> #include <linux/random.h>
#define CREATE_TRACE_POINTS
#include "internal.h" #include "internal.h"
MODULE_DESCRIPTION("AFS Client File System"); MODULE_DESCRIPTION("AFS Client File System");
......
This diff is collapsed.
...@@ -147,7 +147,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr, ...@@ -147,7 +147,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr,
struct key *key, struct key *key,
const char *volname, const char *volname,
struct afs_cache_vlocation *entry, struct afs_cache_vlocation *entry,
const struct afs_wait_mode *wait_mode) bool async)
{ {
struct afs_call *call; struct afs_call *call;
size_t volnamesz, reqsz, padsz; size_t volnamesz, reqsz, padsz;
...@@ -177,7 +177,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr, ...@@ -177,7 +177,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr,
memset((void *) bp + volnamesz, 0, padsz); memset((void *) bp + volnamesz, 0, padsz);
/* initiate the call */ /* initiate the call */
return afs_make_call(addr, call, GFP_KERNEL, wait_mode); return afs_make_call(addr, call, GFP_KERNEL, async);
} }
/* /*
...@@ -188,7 +188,7 @@ int afs_vl_get_entry_by_id(struct in_addr *addr, ...@@ -188,7 +188,7 @@ int afs_vl_get_entry_by_id(struct in_addr *addr,
afs_volid_t volid, afs_volid_t volid,
afs_voltype_t voltype, afs_voltype_t voltype,
struct afs_cache_vlocation *entry, struct afs_cache_vlocation *entry,
const struct afs_wait_mode *wait_mode) bool async)
{ {
struct afs_call *call; struct afs_call *call;
__be32 *bp; __be32 *bp;
...@@ -211,5 +211,5 @@ int afs_vl_get_entry_by_id(struct in_addr *addr, ...@@ -211,5 +211,5 @@ int afs_vl_get_entry_by_id(struct in_addr *addr,
*bp = htonl(voltype); *bp = htonl(voltype);
/* initiate the call */ /* initiate the call */
return afs_make_call(addr, call, GFP_KERNEL, wait_mode); return afs_make_call(addr, call, GFP_KERNEL, async);
} }
...@@ -53,7 +53,7 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl, ...@@ -53,7 +53,7 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
/* attempt to access the VL server */ /* attempt to access the VL server */
ret = afs_vl_get_entry_by_name(&addr, key, vl->vldb.name, vldb, ret = afs_vl_get_entry_by_name(&addr, key, vl->vldb.name, vldb,
&afs_sync_call); false);
switch (ret) { switch (ret) {
case 0: case 0:
goto out; goto out;
...@@ -111,7 +111,7 @@ static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl, ...@@ -111,7 +111,7 @@ static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
/* attempt to access the VL server */ /* attempt to access the VL server */
ret = afs_vl_get_entry_by_id(&addr, key, volid, voltype, vldb, ret = afs_vl_get_entry_by_id(&addr, key, volid, voltype, vldb,
&afs_sync_call); false);
switch (ret) { switch (ret) {
case 0: case 0:
goto out; goto out;
......
...@@ -358,7 +358,7 @@ int afs_vnode_fetch_status(struct afs_vnode *vnode, ...@@ -358,7 +358,7 @@ int afs_vnode_fetch_status(struct afs_vnode *vnode,
server, ntohl(server->addr.s_addr)); server, ntohl(server->addr.s_addr));
ret = afs_fs_fetch_file_status(server, key, vnode, NULL, ret = afs_fs_fetch_file_status(server, key, vnode, NULL,
&afs_sync_call); false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -421,7 +421,7 @@ int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key, ...@@ -421,7 +421,7 @@ int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_fetch_data(server, key, vnode, desc, ret = afs_fs_fetch_data(server, key, vnode, desc,
&afs_sync_call); false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -477,7 +477,7 @@ int afs_vnode_create(struct afs_vnode *vnode, struct key *key, ...@@ -477,7 +477,7 @@ int afs_vnode_create(struct afs_vnode *vnode, struct key *key,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_create(server, key, vnode, name, mode, newfid, ret = afs_fs_create(server, key, vnode, name, mode, newfid,
newstatus, newcb, &afs_sync_call); newstatus, newcb, false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -533,7 +533,7 @@ int afs_vnode_remove(struct afs_vnode *vnode, struct key *key, const char *name, ...@@ -533,7 +533,7 @@ int afs_vnode_remove(struct afs_vnode *vnode, struct key *key, const char *name,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_remove(server, key, vnode, name, isdir, ret = afs_fs_remove(server, key, vnode, name, isdir,
&afs_sync_call); false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -595,7 +595,7 @@ int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode, ...@@ -595,7 +595,7 @@ int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_link(server, key, dvnode, vnode, name, ret = afs_fs_link(server, key, dvnode, vnode, name,
&afs_sync_call); false);
} while (!afs_volume_release_fileserver(dvnode, server, ret)); } while (!afs_volume_release_fileserver(dvnode, server, ret));
...@@ -659,7 +659,7 @@ int afs_vnode_symlink(struct afs_vnode *vnode, struct key *key, ...@@ -659,7 +659,7 @@ int afs_vnode_symlink(struct afs_vnode *vnode, struct key *key,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_symlink(server, key, vnode, name, content, ret = afs_fs_symlink(server, key, vnode, name, content,
newfid, newstatus, &afs_sync_call); newfid, newstatus, false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -729,7 +729,7 @@ int afs_vnode_rename(struct afs_vnode *orig_dvnode, ...@@ -729,7 +729,7 @@ int afs_vnode_rename(struct afs_vnode *orig_dvnode,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_rename(server, key, orig_dvnode, orig_name, ret = afs_fs_rename(server, key, orig_dvnode, orig_name,
new_dvnode, new_name, &afs_sync_call); new_dvnode, new_name, false);
} while (!afs_volume_release_fileserver(orig_dvnode, server, ret)); } while (!afs_volume_release_fileserver(orig_dvnode, server, ret));
...@@ -795,7 +795,7 @@ int afs_vnode_store_data(struct afs_writeback *wb, pgoff_t first, pgoff_t last, ...@@ -795,7 +795,7 @@ int afs_vnode_store_data(struct afs_writeback *wb, pgoff_t first, pgoff_t last,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_store_data(server, wb, first, last, offset, to, ret = afs_fs_store_data(server, wb, first, last, offset, to,
&afs_sync_call); false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -847,7 +847,7 @@ int afs_vnode_setattr(struct afs_vnode *vnode, struct key *key, ...@@ -847,7 +847,7 @@ int afs_vnode_setattr(struct afs_vnode *vnode, struct key *key,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_setattr(server, key, vnode, attr, &afs_sync_call); ret = afs_fs_setattr(server, key, vnode, attr, false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -894,7 +894,7 @@ int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key, ...@@ -894,7 +894,7 @@ int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_get_volume_status(server, key, vnode, vs, &afs_sync_call); ret = afs_fs_get_volume_status(server, key, vnode, vs, false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -933,7 +933,7 @@ int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key, ...@@ -933,7 +933,7 @@ int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key,
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_set_lock(server, key, vnode, type, &afs_sync_call); ret = afs_fs_set_lock(server, key, vnode, type, false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -971,7 +971,7 @@ int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key) ...@@ -971,7 +971,7 @@ int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key)
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_extend_lock(server, key, vnode, &afs_sync_call); ret = afs_fs_extend_lock(server, key, vnode, false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
...@@ -1009,7 +1009,7 @@ int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key) ...@@ -1009,7 +1009,7 @@ int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key)
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
ret = afs_fs_release_lock(server, key, vnode, &afs_sync_call); ret = afs_fs_release_lock(server, key, vnode, false);
} while (!afs_volume_release_fileserver(vnode, server, ret)); } while (!afs_volume_release_fileserver(vnode, server, ret));
......
/* AFS tracepoints
*
* Copyright (C) 2016 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.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM afs
#if !defined(_TRACE_AFS_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_AFS_H
#include <linux/tracepoint.h>
/*
* Define enums for tracing information.
*/
#ifndef __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
#define __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
enum afs_call_trace {
afs_call_trace_alloc,
afs_call_trace_free,
afs_call_trace_put,
afs_call_trace_wake,
afs_call_trace_work,
};
#endif /* end __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY */
/*
* Declare tracing information enums and their string mappings for display.
*/
#define afs_call_traces \
EM(afs_call_trace_alloc, "ALLOC") \
EM(afs_call_trace_free, "FREE ") \
EM(afs_call_trace_put, "PUT ") \
EM(afs_call_trace_wake, "WAKE ") \
E_(afs_call_trace_work, "WORK ")
/*
* Export enum symbols via userspace.
*/
#undef EM
#undef E_
#define EM(a, b) TRACE_DEFINE_ENUM(a);
#define E_(a, b) TRACE_DEFINE_ENUM(a);
afs_call_traces;
/*
* Now redefine the EM() and E_() macros to map the enums to the strings that
* will be printed in the output.
*/
#undef EM
#undef E_
#define EM(a, b) { a, b },
#define E_(a, b) { a, b }
TRACE_EVENT(afs_recv_data,
TP_PROTO(struct afs_call *call, unsigned count, unsigned offset,
bool want_more, int ret),
TP_ARGS(call, count, offset, want_more, ret),
TP_STRUCT__entry(
__field(struct rxrpc_call *, rxcall )
__field(struct afs_call *, call )
__field(enum afs_call_state, state )
__field(unsigned int, count )
__field(unsigned int, offset )
__field(unsigned short, unmarshall )
__field(bool, want_more )
__field(int, ret )
),
TP_fast_assign(
__entry->rxcall = call->rxcall;
__entry->call = call;
__entry->state = call->state;
__entry->unmarshall = call->unmarshall;
__entry->count = count;
__entry->offset = offset;
__entry->want_more = want_more;
__entry->ret = ret;
),
TP_printk("c=%p ac=%p s=%u u=%u %u/%u wm=%u ret=%d",
__entry->rxcall,
__entry->call,
__entry->state, __entry->unmarshall,
__entry->offset, __entry->count,
__entry->want_more, __entry->ret)
);
TRACE_EVENT(afs_notify_call,
TP_PROTO(struct rxrpc_call *rxcall, struct afs_call *call),
TP_ARGS(rxcall, call),
TP_STRUCT__entry(
__field(struct rxrpc_call *, rxcall )
__field(struct afs_call *, call )
__field(enum afs_call_state, state )
__field(unsigned short, unmarshall )
),
TP_fast_assign(
__entry->rxcall = rxcall;
__entry->call = call;
__entry->state = call->state;
__entry->unmarshall = call->unmarshall;
),
TP_printk("c=%p ac=%p s=%u u=%u",
__entry->rxcall,
__entry->call,
__entry->state, __entry->unmarshall)
);
TRACE_EVENT(afs_cb_call,
TP_PROTO(struct afs_call *call),
TP_ARGS(call),
TP_STRUCT__entry(
__field(struct rxrpc_call *, rxcall )
__field(struct afs_call *, call )
__field(const char *, name )
__field(u32, op )
),
TP_fast_assign(
__entry->rxcall = call->rxcall;
__entry->call = call;
__entry->name = call->type->name;
__entry->op = call->operation_ID;
),
TP_printk("c=%p ac=%p %s o=%u",
__entry->rxcall,
__entry->call,
__entry->name,
__entry->op)
);
TRACE_EVENT(afs_call,
TP_PROTO(struct afs_call *call, enum afs_call_trace op,
int usage, int outstanding, const void *where),
TP_ARGS(call, op, usage, outstanding, where),
TP_STRUCT__entry(
__field(struct afs_call *, call )
__field(int, op )
__field(int, usage )
__field(int, outstanding )
__field(const void *, where )
),
TP_fast_assign(
__entry->call = call;
__entry->op = op;
__entry->usage = usage;
__entry->outstanding = outstanding;
__entry->where = where;
),
TP_printk("c=%p %s u=%d o=%d sp=%pSR",
__entry->call,
__print_symbolic(__entry->op, afs_call_traces),
__entry->usage,
__entry->outstanding,
__entry->where)
);
#endif /* _TRACE_AFS_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
...@@ -224,6 +224,14 @@ static int rxrpc_listen(struct socket *sock, int backlog) ...@@ -224,6 +224,14 @@ static int rxrpc_listen(struct socket *sock, int backlog)
else else
sk->sk_max_ack_backlog = old; sk->sk_max_ack_backlog = old;
break; break;
case RXRPC_SERVER_LISTENING:
if (backlog == 0) {
rx->sk.sk_state = RXRPC_SERVER_LISTEN_DISABLED;
sk->sk_max_ack_backlog = 0;
rxrpc_discard_prealloc(rx);
ret = 0;
break;
}
default: default:
ret = -EBUSY; ret = -EBUSY;
break; break;
......
...@@ -60,6 +60,7 @@ enum { ...@@ -60,6 +60,7 @@ enum {
RXRPC_CLIENT_BOUND, /* client local address bound */ RXRPC_CLIENT_BOUND, /* client local address bound */
RXRPC_SERVER_BOUND, /* server local address bound */ RXRPC_SERVER_BOUND, /* server local address bound */
RXRPC_SERVER_LISTENING, /* server listening for connections */ RXRPC_SERVER_LISTENING, /* server listening for connections */
RXRPC_SERVER_LISTEN_DISABLED, /* server listening disabled */
RXRPC_CLOSE, /* socket is being closed */ RXRPC_CLOSE, /* socket is being closed */
}; };
......
...@@ -349,7 +349,8 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local, ...@@ -349,7 +349,8 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
found_service: found_service:
spin_lock(&rx->incoming_lock); spin_lock(&rx->incoming_lock);
if (rx->sk.sk_state == RXRPC_CLOSE) { if (rx->sk.sk_state == RXRPC_SERVER_LISTEN_DISABLED ||
rx->sk.sk_state == RXRPC_CLOSE) {
trace_rxrpc_abort("CLS", sp->hdr.cid, sp->hdr.callNumber, trace_rxrpc_abort("CLS", sp->hdr.cid, sp->hdr.callNumber,
sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN); sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN);
skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT; skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment