Merge tag 'afs-fixes-20190516' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull misc AFS fixes from David Howells: "This fixes a set of miscellaneous issues in the afs filesystem, including: - leak of keys on file close. - broken error handling in xattr functions. - missing locking when updating VL server list. - volume location server DNS lookup whereby preloaded cells may not ever get a lookup and regular DNS lookups to maintain server lists consume power unnecessarily. - incorrect error propagation and handling in the fileserver iteration code causes operations to sometimes apparently succeed. - interruption of server record check/update side op during fileserver iteration causes uninterruptible main operations to fail unexpectedly. - callback promise expiry time miscalculation. - over invalidation of the callback promise on directories. - double locking on callback break waking up file locking waiters. - double increment of the vnode callback break counter. Note that it makes some changes outside of the afs code, including: - an extra parameter to dns_query() to allow the dns_resolver key just accessed to be immediately invalidated. AFS is caching the results itself, so the key can be discarded. - an interruptible version of wait_var_event(). - an rxrpc function to allow the maximum lifespan to be set on a call. - a way for an rxrpc call to be marked as non-interruptible" * tag 'afs-fixes-20190516' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Fix double inc of vnode->cb_break afs: Fix lock-wait/callback-break double locking afs: Don't invalidate callback if AFS_VNODE_DIR_VALID not set afs: Fix calculation of callback expiry time afs: Make dynamic root population wait uninterruptibly for proc_cells_lock afs: Make some RPC operations non-interruptible rxrpc: Allow the kernel to mark a call as being non-interruptible afs: Fix error propagation from server record check/update afs: Fix the maximum lifespan of VL and probe calls rxrpc: Provide kernel interface to set max lifespan on a call afs: Fix "kAFS: AFS vnode with undefined type 0" afs: Fix cell DNS lookup Add wait_var_event_interruptible() dns_resolver: Allow used keys to be invalidated afs: Fix afs_cell records to always have a VL server list record afs: Fix missing lock when replacing VL server list afs: Fix afs_xattr_get_yfs() to not try freeing an error value afs: Fix incorrect error handling in afs_xattr_get_acl() afs: Fix key leak in afs_release() and afs_evict_inode()
这个提交包含在:
@@ -1887,7 +1887,7 @@ static int ceph_dns_resolve_name(const char *name, size_t namelen,
|
||||
return -EINVAL;
|
||||
|
||||
/* do dns_resolve upcall */
|
||||
ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL);
|
||||
ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL, false);
|
||||
if (ip_len > 0)
|
||||
ret = ceph_pton(ip_addr, ip_len, addr, -1, NULL);
|
||||
else
|
||||
|
@@ -54,6 +54,7 @@
|
||||
* @options: Request options (or NULL if no options)
|
||||
* @_result: Where to place the returned data (or NULL)
|
||||
* @_expiry: Where to store the result expiry time (or NULL)
|
||||
* @invalidate: Always invalidate the key after use
|
||||
*
|
||||
* The data will be returned in the pointer at *result, if provided, and the
|
||||
* caller is responsible for freeing it.
|
||||
@@ -69,7 +70,8 @@
|
||||
* Returns the size of the result on success, -ve error code otherwise.
|
||||
*/
|
||||
int dns_query(const char *type, const char *name, size_t namelen,
|
||||
const char *options, char **_result, time64_t *_expiry)
|
||||
const char *options, char **_result, time64_t *_expiry,
|
||||
bool invalidate)
|
||||
{
|
||||
struct key *rkey;
|
||||
struct user_key_payload *upayload;
|
||||
@@ -157,6 +159,8 @@ int dns_query(const char *type, const char *name, size_t namelen,
|
||||
ret = len;
|
||||
put:
|
||||
up_read(&rkey->sem);
|
||||
if (invalidate)
|
||||
key_invalidate(rkey);
|
||||
key_put(rkey);
|
||||
out:
|
||||
kleave(" = %d", ret);
|
||||
|
@@ -270,6 +270,7 @@ static int rxrpc_listen(struct socket *sock, int backlog)
|
||||
* @gfp: The allocation constraints
|
||||
* @notify_rx: Where to send notifications instead of socket queue
|
||||
* @upgrade: Request service upgrade for call
|
||||
* @intr: The call is interruptible
|
||||
* @debug_id: The debug ID for tracing to be assigned to the call
|
||||
*
|
||||
* Allow a kernel service to begin a call on the nominated socket. This just
|
||||
@@ -287,6 +288,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
|
||||
gfp_t gfp,
|
||||
rxrpc_notify_rx_t notify_rx,
|
||||
bool upgrade,
|
||||
bool intr,
|
||||
unsigned int debug_id)
|
||||
{
|
||||
struct rxrpc_conn_parameters cp;
|
||||
@@ -311,6 +313,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.user_call_ID = user_call_ID;
|
||||
p.tx_total_len = tx_total_len;
|
||||
p.intr = intr;
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
cp.local = rx->local;
|
||||
@@ -443,6 +446,31 @@ void rxrpc_kernel_new_call_notification(
|
||||
}
|
||||
EXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
|
||||
|
||||
/**
|
||||
* rxrpc_kernel_set_max_life - Set maximum lifespan on a call
|
||||
* @sock: The socket the call is on
|
||||
* @call: The call to configure
|
||||
* @hard_timeout: The maximum lifespan of the call in jiffies
|
||||
*
|
||||
* Set the maximum lifespan of a call. The call will end with ETIME or
|
||||
* ETIMEDOUT if it takes longer than this.
|
||||
*/
|
||||
void rxrpc_kernel_set_max_life(struct socket *sock, struct rxrpc_call *call,
|
||||
unsigned long hard_timeout)
|
||||
{
|
||||
unsigned long now;
|
||||
|
||||
mutex_lock(&call->user_mutex);
|
||||
|
||||
now = jiffies;
|
||||
hard_timeout += now;
|
||||
WRITE_ONCE(call->expect_term_by, hard_timeout);
|
||||
rxrpc_reduce_call_timer(call, hard_timeout, now, rxrpc_timer_set_for_hard);
|
||||
|
||||
mutex_unlock(&call->user_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(rxrpc_kernel_set_max_life);
|
||||
|
||||
/*
|
||||
* connect an RxRPC socket
|
||||
* - this just targets it at a specific destination; no actual connection
|
||||
|
@@ -482,6 +482,7 @@ enum rxrpc_call_flag {
|
||||
RXRPC_CALL_BEGAN_RX_TIMER, /* We began the expect_rx_by timer */
|
||||
RXRPC_CALL_RX_HEARD, /* The peer responded at least once to this call */
|
||||
RXRPC_CALL_RX_UNDERRUN, /* Got data underrun */
|
||||
RXRPC_CALL_IS_INTR, /* The call is interruptible */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -711,6 +712,7 @@ struct rxrpc_call_params {
|
||||
u32 normal; /* Max time since last call packet (msec) */
|
||||
} timeouts;
|
||||
u8 nr_timeouts; /* Number of timeouts specified */
|
||||
bool intr; /* The call is interruptible */
|
||||
};
|
||||
|
||||
struct rxrpc_send_params {
|
||||
|
@@ -241,6 +241,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
|
||||
return call;
|
||||
}
|
||||
|
||||
if (p->intr)
|
||||
__set_bit(RXRPC_CALL_IS_INTR, &call->flags);
|
||||
call->tx_total_len = p->tx_total_len;
|
||||
trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage),
|
||||
here, (const void *)p->user_call_ID);
|
||||
|
@@ -656,10 +656,14 @@ static int rxrpc_wait_for_channel(struct rxrpc_call *call, gfp_t gfp)
|
||||
|
||||
add_wait_queue_exclusive(&call->waitq, &myself);
|
||||
for (;;) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (test_bit(RXRPC_CALL_IS_INTR, &call->flags))
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
else
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
if (call->call_id)
|
||||
break;
|
||||
if (signal_pending(current)) {
|
||||
if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) &&
|
||||
signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
@@ -80,7 +80,8 @@ static int rxrpc_wait_for_tx_window_nonintr(struct rxrpc_sock *rx,
|
||||
if (call->state >= RXRPC_CALL_COMPLETE)
|
||||
return call->error;
|
||||
|
||||
if (timeout == 0 &&
|
||||
if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) &&
|
||||
timeout == 0 &&
|
||||
tx_win == tx_start && signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
@@ -620,6 +621,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
|
||||
.call.tx_total_len = -1,
|
||||
.call.user_call_ID = 0,
|
||||
.call.nr_timeouts = 0,
|
||||
.call.intr = true,
|
||||
.abort_code = 0,
|
||||
.command = RXRPC_CMD_SEND_DATA,
|
||||
.exclusive = false,
|
||||
|
在新工单中引用
屏蔽一个用户