mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
Merge tag 'v5.12-rc5' into android-mainline
Linux 5.12-rc5 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I20408e2b65a5e6f4bd83b6c1ac55c50cd084d1da
This commit is contained in:
2
Makefile
2
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 12
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc4
|
||||
EXTRAVERSION = -rc5
|
||||
NAME = Frozen Wasteland
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -27,7 +27,7 @@ endif
|
||||
REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING \
|
||||
-Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
|
||||
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \
|
||||
-mno-mmx -mno-sse
|
||||
-mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
|
||||
|
||||
REALMODE_CFLAGS += -ffreestanding
|
||||
REALMODE_CFLAGS += -fno-stack-protector
|
||||
|
||||
@@ -262,7 +262,7 @@ static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
|
||||
if (pgprot_val(old_prot) == pgprot_val(new_prot))
|
||||
return;
|
||||
|
||||
pa = pfn << page_level_shift(level);
|
||||
pa = pfn << PAGE_SHIFT;
|
||||
size = page_level_size(level);
|
||||
|
||||
/*
|
||||
|
||||
21
block/bio.c
21
block/bio.c
@@ -949,7 +949,7 @@ void bio_release_pages(struct bio *bio, bool mark_dirty)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bio_release_pages);
|
||||
|
||||
static int bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
|
||||
static void __bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
|
||||
{
|
||||
WARN_ON_ONCE(bio->bi_max_vecs);
|
||||
|
||||
@@ -959,11 +959,26 @@ static int bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
|
||||
bio->bi_iter.bi_size = iter->count;
|
||||
bio_set_flag(bio, BIO_NO_PAGE_REF);
|
||||
bio_set_flag(bio, BIO_CLONED);
|
||||
}
|
||||
|
||||
static int bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
|
||||
{
|
||||
__bio_iov_bvec_set(bio, iter);
|
||||
iov_iter_advance(iter, iter->count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bio_iov_bvec_set_append(struct bio *bio, struct iov_iter *iter)
|
||||
{
|
||||
struct request_queue *q = bio->bi_bdev->bd_disk->queue;
|
||||
struct iov_iter i = *iter;
|
||||
|
||||
iov_iter_truncate(&i, queue_max_zone_append_sectors(q) << 9);
|
||||
__bio_iov_bvec_set(bio, &i);
|
||||
iov_iter_advance(iter, i.count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PAGE_PTRS_PER_BVEC (sizeof(struct bio_vec) / sizeof(struct page *))
|
||||
|
||||
/**
|
||||
@@ -1094,8 +1109,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
||||
int ret = 0;
|
||||
|
||||
if (iov_iter_is_bvec(iter)) {
|
||||
if (WARN_ON_ONCE(bio_op(bio) == REQ_OP_ZONE_APPEND))
|
||||
return -EINVAL;
|
||||
if (bio_op(bio) == REQ_OP_ZONE_APPEND)
|
||||
return bio_iov_bvec_set_append(bio, iter);
|
||||
return bio_iov_bvec_set(bio, iter);
|
||||
}
|
||||
|
||||
|
||||
@@ -382,6 +382,14 @@ unsigned int blk_recalc_rq_segments(struct request *rq)
|
||||
switch (bio_op(rq->bio)) {
|
||||
case REQ_OP_DISCARD:
|
||||
case REQ_OP_SECURE_ERASE:
|
||||
if (queue_max_discard_segments(rq->q) > 1) {
|
||||
struct bio *bio = rq->bio;
|
||||
|
||||
for_each_bio(bio)
|
||||
nr_phys_segs++;
|
||||
return nr_phys_segs;
|
||||
}
|
||||
return 1;
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
return 0;
|
||||
case REQ_OP_WRITE_SAME:
|
||||
|
||||
@@ -322,6 +322,13 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
|
||||
const char *dname;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* disk_max_parts() won't be zero, either GENHD_FL_EXT_DEVT is set
|
||||
* or 'minors' is passed to alloc_disk().
|
||||
*/
|
||||
if (partno >= disk_max_parts(disk))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/*
|
||||
* Partitions are not supported on zoned block devices that are used as
|
||||
* such.
|
||||
|
||||
@@ -470,12 +470,14 @@ static ssize_t charlcd_write(struct file *file, const char __user *buf,
|
||||
char c;
|
||||
|
||||
for (; count-- > 0; (*ppos)++, tmp++) {
|
||||
if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
|
||||
if (((count + 1) & 0x1f) == 0) {
|
||||
/*
|
||||
* let's be a little nice with other processes
|
||||
* that need some CPU
|
||||
* charlcd_write() is invoked as a VFS->write() callback
|
||||
* and as such it is always invoked from preemptible
|
||||
* context and may sleep.
|
||||
*/
|
||||
schedule();
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (get_user(c, tmp))
|
||||
return -EFAULT;
|
||||
@@ -537,12 +539,8 @@ static void charlcd_puts(struct charlcd *lcd, const char *s)
|
||||
int count = strlen(s);
|
||||
|
||||
for (; count-- > 0; tmp++) {
|
||||
if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
|
||||
/*
|
||||
* let's be a little nice with other processes
|
||||
* that need some CPU
|
||||
*/
|
||||
schedule();
|
||||
if (((count + 1) & 0x1f) == 0)
|
||||
cond_resched();
|
||||
|
||||
charlcd_write_char(lcd, *tmp);
|
||||
}
|
||||
|
||||
@@ -2371,6 +2371,24 @@ static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ibmvfc_event_is_free - Check if event is free or not
|
||||
* @evt: ibmvfc event struct
|
||||
*
|
||||
* Returns:
|
||||
* true / false
|
||||
**/
|
||||
static bool ibmvfc_event_is_free(struct ibmvfc_event *evt)
|
||||
{
|
||||
struct ibmvfc_event *loop_evt;
|
||||
|
||||
list_for_each_entry(loop_evt, &evt->queue->free, queue_list)
|
||||
if (loop_evt == evt)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ibmvfc_wait_for_ops - Wait for ops to complete
|
||||
* @vhost: ibmvfc host struct
|
||||
@@ -2385,35 +2403,58 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
|
||||
{
|
||||
struct ibmvfc_event *evt;
|
||||
DECLARE_COMPLETION_ONSTACK(comp);
|
||||
int wait;
|
||||
int wait, i, q_index, q_size;
|
||||
unsigned long flags;
|
||||
signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ;
|
||||
struct ibmvfc_queue *queues;
|
||||
|
||||
ENTER;
|
||||
if (vhost->mq_enabled && vhost->using_channels) {
|
||||
queues = vhost->scsi_scrqs.scrqs;
|
||||
q_size = vhost->scsi_scrqs.active_queues;
|
||||
} else {
|
||||
queues = &vhost->crq;
|
||||
q_size = 1;
|
||||
}
|
||||
|
||||
do {
|
||||
wait = 0;
|
||||
spin_lock_irqsave(&vhost->crq.l_lock, flags);
|
||||
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
|
||||
if (match(evt, device)) {
|
||||
evt->eh_comp = ∁
|
||||
wait++;
|
||||
spin_lock_irqsave(vhost->host->host_lock, flags);
|
||||
for (q_index = 0; q_index < q_size; q_index++) {
|
||||
spin_lock(&queues[q_index].l_lock);
|
||||
for (i = 0; i < queues[q_index].evt_pool.size; i++) {
|
||||
evt = &queues[q_index].evt_pool.events[i];
|
||||
if (!ibmvfc_event_is_free(evt)) {
|
||||
if (match(evt, device)) {
|
||||
evt->eh_comp = ∁
|
||||
wait++;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&queues[q_index].l_lock);
|
||||
}
|
||||
spin_unlock_irqrestore(&vhost->crq.l_lock, flags);
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
|
||||
if (wait) {
|
||||
timeout = wait_for_completion_timeout(&comp, timeout);
|
||||
|
||||
if (!timeout) {
|
||||
wait = 0;
|
||||
spin_lock_irqsave(&vhost->crq.l_lock, flags);
|
||||
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
|
||||
if (match(evt, device)) {
|
||||
evt->eh_comp = NULL;
|
||||
wait++;
|
||||
spin_lock_irqsave(vhost->host->host_lock, flags);
|
||||
for (q_index = 0; q_index < q_size; q_index++) {
|
||||
spin_lock(&queues[q_index].l_lock);
|
||||
for (i = 0; i < queues[q_index].evt_pool.size; i++) {
|
||||
evt = &queues[q_index].evt_pool.events[i];
|
||||
if (!ibmvfc_event_is_free(evt)) {
|
||||
if (match(evt, device)) {
|
||||
evt->eh_comp = NULL;
|
||||
wait++;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&queues[q_index].l_lock);
|
||||
}
|
||||
spin_unlock_irqrestore(&vhost->crq.l_lock, flags);
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
if (wait)
|
||||
dev_err(vhost->dev, "Timed out waiting for aborted commands\n");
|
||||
LEAVE;
|
||||
|
||||
@@ -7806,14 +7806,18 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
||||
ioc->pend_os_device_add_sz++;
|
||||
ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz,
|
||||
GFP_KERNEL);
|
||||
if (!ioc->pend_os_device_add)
|
||||
if (!ioc->pend_os_device_add) {
|
||||
r = -ENOMEM;
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
ioc->device_remove_in_progress_sz = ioc->pend_os_device_add_sz;
|
||||
ioc->device_remove_in_progress =
|
||||
kzalloc(ioc->device_remove_in_progress_sz, GFP_KERNEL);
|
||||
if (!ioc->device_remove_in_progress)
|
||||
if (!ioc->device_remove_in_progress) {
|
||||
r = -ENOMEM;
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
ioc->fwfault_debug = mpt3sas_fwfault_debug;
|
||||
|
||||
|
||||
@@ -1675,6 +1675,7 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
|
||||
if (!qedi->global_queues[i]) {
|
||||
QEDI_ERR(&qedi->dbg_ctx,
|
||||
"Unable to allocation global queue %d.\n", i);
|
||||
status = -ENOMEM;
|
||||
goto mem_alloc_failure;
|
||||
}
|
||||
|
||||
|
||||
@@ -3222,8 +3222,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
|
||||
if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
|
||||
(cmd->sess && cmd->sess->deleted)) {
|
||||
cmd->state = QLA_TGT_STATE_PROCESSED;
|
||||
res = 0;
|
||||
goto free;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018,
|
||||
@@ -3234,8 +3233,9 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
|
||||
|
||||
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
|
||||
&full_req_cnt);
|
||||
if (unlikely(res != 0))
|
||||
goto free;
|
||||
if (unlikely(res != 0)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
|
||||
|
||||
@@ -3255,8 +3255,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
|
||||
vha->flags.online, qla2x00_reset_active(vha),
|
||||
cmd->reset_count, qpair->chip_reset);
|
||||
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
||||
res = 0;
|
||||
goto free;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Does F/W have an IOCBs for this request */
|
||||
@@ -3359,8 +3358,6 @@ out_unmap_unlock:
|
||||
qlt_unmap_sg(vha, cmd);
|
||||
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
||||
|
||||
free:
|
||||
vha->hw->tgt.tgt_ops->free_cmd(cmd);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(qlt_xmit_response);
|
||||
|
||||
@@ -644,7 +644,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct qla_tgt_cmd *cmd = container_of(se_cmd,
|
||||
struct qla_tgt_cmd, se_cmd);
|
||||
struct scsi_qla_host *vha = cmd->vha;
|
||||
|
||||
if (cmd->aborted) {
|
||||
/* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task
|
||||
@@ -657,7 +656,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
|
||||
cmd->se_cmd.transport_state,
|
||||
cmd->se_cmd.t_state,
|
||||
cmd->se_cmd.se_cmd_flags);
|
||||
vha->hw->tgt.tgt_ops->free_cmd(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -685,7 +683,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct qla_tgt_cmd *cmd = container_of(se_cmd,
|
||||
struct qla_tgt_cmd, se_cmd);
|
||||
struct scsi_qla_host *vha = cmd->vha;
|
||||
int xmit_type = QLA_TGT_XMIT_STATUS;
|
||||
|
||||
if (cmd->aborted) {
|
||||
@@ -699,7 +696,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
|
||||
cmd, kref_read(&cmd->se_cmd.cmd_kref),
|
||||
cmd->se_cmd.transport_state, cmd->se_cmd.t_state,
|
||||
cmd->se_cmd.se_cmd_flags);
|
||||
vha->hw->tgt.tgt_ops->free_cmd(cmd);
|
||||
return 0;
|
||||
}
|
||||
cmd->bufflen = se_cmd->data_length;
|
||||
|
||||
@@ -882,7 +882,6 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
|
||||
if (!bio) {
|
||||
new_bio:
|
||||
nr_vecs = bio_max_segs(nr_pages);
|
||||
nr_pages -= nr_vecs;
|
||||
/*
|
||||
* Calls bio_kmalloc() and sets bio->bi_end_io()
|
||||
*/
|
||||
@@ -939,6 +938,14 @@ new_bio:
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
if (bio)
|
||||
bio_put(bio);
|
||||
while (req->bio) {
|
||||
bio = req->bio;
|
||||
req->bio = bio->bi_next;
|
||||
bio_put(bio);
|
||||
}
|
||||
req->biotail = NULL;
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1240,13 +1240,13 @@ int bdev_disk_changed(struct block_device *bdev, bool invalidate)
|
||||
|
||||
lockdep_assert_held(&bdev->bd_mutex);
|
||||
|
||||
clear_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
|
||||
|
||||
rescan:
|
||||
ret = blk_drop_partitions(bdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clear_bit(GD_NEED_PART_SCAN, &disk->state);
|
||||
|
||||
/*
|
||||
* Historically we only set the capacity to zero for devices that
|
||||
* support partitions (independ of actually having partitions created).
|
||||
|
||||
@@ -1130,8 +1130,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
||||
}
|
||||
|
||||
/* If it's any one of the ACE we're replacing, skip! */
|
||||
if (!mode_from_sid &&
|
||||
((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
|
||||
if (((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
|
||||
(compare_sids(&pntace->sid, pownersid) == 0) ||
|
||||
(compare_sids(&pntace->sid, pgrpsid) == 0) ||
|
||||
(compare_sids(&pntace->sid, &sid_everyone) == 0) ||
|
||||
|
||||
@@ -919,8 +919,8 @@ struct cifs_ses {
|
||||
bool binding:1; /* are we binding the session? */
|
||||
__u16 session_flags;
|
||||
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
|
||||
__u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
|
||||
__u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
|
||||
__u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
|
||||
__u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
|
||||
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
|
||||
|
||||
__u8 binding_preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
|
||||
|
||||
@@ -147,6 +147,11 @@
|
||||
*/
|
||||
#define SMB3_SIGN_KEY_SIZE (16)
|
||||
|
||||
/*
|
||||
* Size of the smb3 encryption/decryption keys
|
||||
*/
|
||||
#define SMB3_ENC_DEC_KEY_SIZE (32)
|
||||
|
||||
#define CIFS_CLIENT_CHALLENGE_SIZE (8)
|
||||
#define CIFS_SERVER_CHALLENGE_SIZE (8)
|
||||
#define CIFS_HMAC_MD5_HASH_SIZE (16)
|
||||
|
||||
@@ -165,6 +165,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
|
||||
goto posix_open_ret;
|
||||
}
|
||||
} else {
|
||||
cifs_revalidate_mapping(*pinode);
|
||||
cifs_fattr_to_inode(*pinode, &fattr);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#define SMB2_HMACSHA256_SIZE (32)
|
||||
#define SMB2_CMACAES_SIZE (16)
|
||||
#define SMB3_SIGNKEY_SIZE (16)
|
||||
#define SMB3_GCM128_CRYPTKEY_SIZE (16)
|
||||
#define SMB3_GCM256_CRYPTKEY_SIZE (32)
|
||||
|
||||
/* Maximum buffer size value we can send with 1 credit */
|
||||
|
||||
@@ -754,8 +754,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
|
||||
}
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
|
||||
return false;
|
||||
cifs_dbg(FYI, "No file id matched, oplock break ignored\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -2038,6 +2038,7 @@ smb2_duplicate_extents(const unsigned int xid,
|
||||
{
|
||||
int rc;
|
||||
unsigned int ret_data_len;
|
||||
struct inode *inode;
|
||||
struct duplicate_extents_to_file dup_ext_buf;
|
||||
struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
|
||||
|
||||
@@ -2054,10 +2055,21 @@ smb2_duplicate_extents(const unsigned int xid,
|
||||
cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n",
|
||||
src_off, dest_off, len);
|
||||
|
||||
rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
|
||||
if (rc)
|
||||
goto duplicate_extents_out;
|
||||
inode = d_inode(trgtfile->dentry);
|
||||
if (inode->i_size < dest_off + len) {
|
||||
rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
|
||||
if (rc)
|
||||
goto duplicate_extents_out;
|
||||
|
||||
/*
|
||||
* Although also could set plausible allocation size (i_blocks)
|
||||
* here in addition to setting the file size, in reflink
|
||||
* it is likely that the target file is sparse. Its allocation
|
||||
* size will be queried on next revalidate, but it is important
|
||||
* to make sure that file's cached size is updated immediately
|
||||
*/
|
||||
cifs_setsize(inode, dest_off + len);
|
||||
}
|
||||
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
|
||||
trgtfile->fid.volatile_fid,
|
||||
FSCTL_DUPLICATE_EXTENTS_TO_FILE,
|
||||
@@ -4158,7 +4170,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
|
||||
if (ses->Suid == ses_id) {
|
||||
ses_enc_key = enc ? ses->smb3encryptionkey :
|
||||
ses->smb3decryptionkey;
|
||||
memcpy(key, ses_enc_key, SMB3_SIGN_KEY_SIZE);
|
||||
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -4185,7 +4197,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
|
||||
int rc = 0;
|
||||
struct scatterlist *sg;
|
||||
u8 sign[SMB2_SIGNATURE_SIZE] = {};
|
||||
u8 key[SMB3_SIGN_KEY_SIZE];
|
||||
u8 key[SMB3_ENC_DEC_KEY_SIZE];
|
||||
struct aead_request *req;
|
||||
char *iv;
|
||||
unsigned int iv_len;
|
||||
@@ -4209,10 +4221,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
|
||||
tfm = enc ? server->secmech.ccmaesencrypt :
|
||||
server->secmech.ccmaesdecrypt;
|
||||
|
||||
if (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
|
||||
if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
|
||||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
|
||||
rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
|
||||
else
|
||||
rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
|
||||
rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
|
||||
|
||||
if (rc) {
|
||||
cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
|
||||
|
||||
@@ -298,7 +298,8 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
|
||||
{
|
||||
unsigned char zero = 0x0;
|
||||
__u8 i[4] = {0, 0, 0, 1};
|
||||
__u8 L[4] = {0, 0, 0, 128};
|
||||
__u8 L128[4] = {0, 0, 0, 128};
|
||||
__u8 L256[4] = {0, 0, 1, 0};
|
||||
int rc = 0;
|
||||
unsigned char prfhash[SMB2_HMACSHA256_SIZE];
|
||||
unsigned char *hashptr = prfhash;
|
||||
@@ -354,8 +355,14 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
L, 4);
|
||||
if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
|
||||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
L256, 4);
|
||||
} else {
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
L128, 4);
|
||||
}
|
||||
if (rc) {
|
||||
cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
@@ -390,6 +397,9 @@ generate_smb3signingkey(struct cifs_ses *ses,
|
||||
const struct derivation_triplet *ptriplet)
|
||||
{
|
||||
int rc;
|
||||
#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* All channels use the same encryption/decryption keys but
|
||||
@@ -422,11 +432,11 @@ generate_smb3signingkey(struct cifs_ses *ses,
|
||||
rc = generate_key(ses, ptriplet->encryption.label,
|
||||
ptriplet->encryption.context,
|
||||
ses->smb3encryptionkey,
|
||||
SMB3_SIGN_KEY_SIZE);
|
||||
SMB3_ENC_DEC_KEY_SIZE);
|
||||
rc = generate_key(ses, ptriplet->decryption.label,
|
||||
ptriplet->decryption.context,
|
||||
ses->smb3decryptionkey,
|
||||
SMB3_SIGN_KEY_SIZE);
|
||||
SMB3_ENC_DEC_KEY_SIZE);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@@ -442,14 +452,23 @@ generate_smb3signingkey(struct cifs_ses *ses,
|
||||
*/
|
||||
cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
|
||||
&ses->Suid);
|
||||
cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);
|
||||
cifs_dbg(VFS, "Session Key %*ph\n",
|
||||
SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
|
||||
cifs_dbg(VFS, "Signing Key %*ph\n",
|
||||
SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
|
||||
cifs_dbg(VFS, "ServerIn Key %*ph\n",
|
||||
SMB3_SIGN_KEY_SIZE, ses->smb3encryptionkey);
|
||||
cifs_dbg(VFS, "ServerOut Key %*ph\n",
|
||||
SMB3_SIGN_KEY_SIZE, ses->smb3decryptionkey);
|
||||
if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
|
||||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
|
||||
cifs_dbg(VFS, "ServerIn Key %*ph\n",
|
||||
SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);
|
||||
cifs_dbg(VFS, "ServerOut Key %*ph\n",
|
||||
SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);
|
||||
} else {
|
||||
cifs_dbg(VFS, "ServerIn Key %*ph\n",
|
||||
SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);
|
||||
cifs_dbg(VFS, "ServerOut Key %*ph\n",
|
||||
SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
32
fs/io-wq.c
32
fs/io-wq.c
@@ -16,7 +16,6 @@
|
||||
#include <linux/rculist_nulls.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/tracehook.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include "../kernel/sched/sched.h"
|
||||
#include "io-wq.h"
|
||||
@@ -388,11 +387,9 @@ static struct io_wq_work *io_get_next_work(struct io_wqe *wqe)
|
||||
|
||||
static bool io_flush_signals(void)
|
||||
{
|
||||
if (unlikely(test_tsk_thread_flag(current, TIF_NOTIFY_SIGNAL))) {
|
||||
if (unlikely(test_thread_flag(TIF_NOTIFY_SIGNAL))) {
|
||||
__set_current_state(TASK_RUNNING);
|
||||
if (current->task_works)
|
||||
task_work_run();
|
||||
clear_tsk_thread_flag(current, TIF_NOTIFY_SIGNAL);
|
||||
tracehook_notify_signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -505,10 +502,15 @@ loop:
|
||||
if (io_flush_signals())
|
||||
continue;
|
||||
ret = schedule_timeout(WORKER_IDLE_TIMEOUT);
|
||||
if (try_to_freeze() || ret)
|
||||
continue;
|
||||
if (fatal_signal_pending(current))
|
||||
if (signal_pending(current)) {
|
||||
struct ksignal ksig;
|
||||
|
||||
if (!get_signal(&ksig))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
continue;
|
||||
/* timed out, exit unless we're the fixed worker */
|
||||
if (test_bit(IO_WQ_BIT_EXIT, &wq->state) ||
|
||||
!(worker->flags & IO_WORKER_F_FIXED))
|
||||
@@ -716,9 +718,13 @@ static int io_wq_manager(void *data)
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
io_wq_check_workers(wq);
|
||||
schedule_timeout(HZ);
|
||||
try_to_freeze();
|
||||
if (fatal_signal_pending(current))
|
||||
if (signal_pending(current)) {
|
||||
struct ksignal ksig;
|
||||
|
||||
if (!get_signal(&ksig))
|
||||
continue;
|
||||
set_bit(IO_WQ_BIT_EXIT, &wq->state);
|
||||
}
|
||||
} while (!test_bit(IO_WQ_BIT_EXIT, &wq->state));
|
||||
|
||||
io_wq_check_workers(wq);
|
||||
@@ -1065,7 +1071,11 @@ static void io_wq_destroy(struct io_wq *wq)
|
||||
|
||||
for_each_node(node) {
|
||||
struct io_wqe *wqe = wq->wqes[node];
|
||||
WARN_ON_ONCE(!wq_list_empty(&wqe->work_list));
|
||||
struct io_cb_cancel_data match = {
|
||||
.fn = io_wq_work_match_all,
|
||||
.cancel_all = true,
|
||||
};
|
||||
io_wqe_cancel_pending_work(wqe, &match);
|
||||
kfree(wqe);
|
||||
}
|
||||
io_wq_put_hash(wq->hash);
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
#include <linux/task_work.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/io_uring.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/io_uring.h>
|
||||
@@ -1095,8 +1094,6 @@ static bool io_match_task(struct io_kiocb *head,
|
||||
io_for_each_link(req, head) {
|
||||
if (req->flags & REQ_F_INFLIGHT)
|
||||
return true;
|
||||
if (req->task->files == files)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1239,16 +1236,16 @@ static void io_queue_async_work(struct io_kiocb *req)
|
||||
BUG_ON(!tctx);
|
||||
BUG_ON(!tctx->io_wq);
|
||||
|
||||
trace_io_uring_queue_async_work(ctx, io_wq_is_hashed(&req->work), req,
|
||||
&req->work, req->flags);
|
||||
/* init ->work of the whole link before punting */
|
||||
io_prep_async_link(req);
|
||||
trace_io_uring_queue_async_work(ctx, io_wq_is_hashed(&req->work), req,
|
||||
&req->work, req->flags);
|
||||
io_wq_enqueue(tctx->io_wq, &req->work);
|
||||
if (link)
|
||||
io_queue_linked_timeout(link);
|
||||
}
|
||||
|
||||
static void io_kill_timeout(struct io_kiocb *req)
|
||||
static void io_kill_timeout(struct io_kiocb *req, int status)
|
||||
{
|
||||
struct io_timeout_data *io = req->async_data;
|
||||
int ret;
|
||||
@@ -1258,31 +1255,11 @@ static void io_kill_timeout(struct io_kiocb *req)
|
||||
atomic_set(&req->ctx->cq_timeouts,
|
||||
atomic_read(&req->ctx->cq_timeouts) + 1);
|
||||
list_del_init(&req->timeout.list);
|
||||
io_cqring_fill_event(req, 0);
|
||||
io_cqring_fill_event(req, status);
|
||||
io_put_req_deferred(req, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if we found and killed one or more timeouts
|
||||
*/
|
||||
static bool io_kill_timeouts(struct io_ring_ctx *ctx, struct task_struct *tsk,
|
||||
struct files_struct *files)
|
||||
{
|
||||
struct io_kiocb *req, *tmp;
|
||||
int canceled = 0;
|
||||
|
||||
spin_lock_irq(&ctx->completion_lock);
|
||||
list_for_each_entry_safe(req, tmp, &ctx->timeout_list, timeout.list) {
|
||||
if (io_match_task(req, tsk, files)) {
|
||||
io_kill_timeout(req);
|
||||
canceled++;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&ctx->completion_lock);
|
||||
return canceled != 0;
|
||||
}
|
||||
|
||||
static void __io_queue_deferred(struct io_ring_ctx *ctx)
|
||||
{
|
||||
do {
|
||||
@@ -1327,7 +1304,7 @@ static void io_flush_timeouts(struct io_ring_ctx *ctx)
|
||||
break;
|
||||
|
||||
list_del_init(&req->timeout.list);
|
||||
io_kill_timeout(req);
|
||||
io_kill_timeout(req, 0);
|
||||
} while (!list_empty(&ctx->timeout_list));
|
||||
|
||||
ctx->cq_last_tm_flush = seq;
|
||||
@@ -2524,13 +2501,12 @@ static void __io_complete_rw(struct io_kiocb *req, long res, long res2,
|
||||
{
|
||||
int cflags = 0;
|
||||
|
||||
if (req->rw.kiocb.ki_flags & IOCB_WRITE)
|
||||
kiocb_end_write(req);
|
||||
if ((res == -EAGAIN || res == -EOPNOTSUPP) && io_rw_reissue(req))
|
||||
return;
|
||||
if (res != req->result)
|
||||
req_set_fail_links(req);
|
||||
|
||||
if (req->rw.kiocb.ki_flags & IOCB_WRITE)
|
||||
kiocb_end_write(req);
|
||||
if (req->flags & REQ_F_BUFFER_SELECTED)
|
||||
cflags = io_put_rw_kbuf(req);
|
||||
__io_req_complete(req, issue_flags, res, cflags);
|
||||
@@ -3978,6 +3954,7 @@ static int io_remove_buffers(struct io_kiocb *req, unsigned int issue_flags)
|
||||
static int io_provide_buffers_prep(struct io_kiocb *req,
|
||||
const struct io_uring_sqe *sqe)
|
||||
{
|
||||
unsigned long size;
|
||||
struct io_provide_buf *p = &req->pbuf;
|
||||
u64 tmp;
|
||||
|
||||
@@ -3991,7 +3968,8 @@ static int io_provide_buffers_prep(struct io_kiocb *req,
|
||||
p->addr = READ_ONCE(sqe->addr);
|
||||
p->len = READ_ONCE(sqe->len);
|
||||
|
||||
if (!access_ok(u64_to_user_ptr(p->addr), (p->len * p->nbufs)))
|
||||
size = (unsigned long)p->len * p->nbufs;
|
||||
if (!access_ok(u64_to_user_ptr(p->addr), size))
|
||||
return -EFAULT;
|
||||
|
||||
p->bgid = READ_ONCE(sqe->buf_group);
|
||||
@@ -4820,7 +4798,6 @@ static int io_connect(struct io_kiocb *req, unsigned int issue_flags)
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
io = req->async_data;
|
||||
memcpy(req->async_data, &__io, sizeof(__io));
|
||||
return -EAGAIN;
|
||||
}
|
||||
@@ -5583,7 +5560,8 @@ static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
|
||||
|
||||
data->mode = io_translate_timeout_mode(flags);
|
||||
hrtimer_init(&data->timer, CLOCK_MONOTONIC, data->mode);
|
||||
io_req_track_inflight(req);
|
||||
if (is_timeout_link)
|
||||
io_req_track_inflight(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6479,8 +6457,6 @@ static int io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
|
||||
ret = io_init_req(ctx, req, sqe);
|
||||
if (unlikely(ret)) {
|
||||
fail_req:
|
||||
io_put_req(req);
|
||||
io_req_complete(req, ret);
|
||||
if (link->head) {
|
||||
/* fail even hard links since we don't submit */
|
||||
link->head->flags |= REQ_F_FAIL_LINK;
|
||||
@@ -6488,6 +6464,8 @@ fail_req:
|
||||
io_req_complete(link->head, -ECANCELED);
|
||||
link->head = NULL;
|
||||
}
|
||||
io_put_req(req);
|
||||
io_req_complete(req, ret);
|
||||
return ret;
|
||||
}
|
||||
ret = io_req_prep(req, sqe);
|
||||
@@ -6764,8 +6742,13 @@ static int io_sq_thread(void *data)
|
||||
timeout = jiffies + sqd->sq_thread_idle;
|
||||
continue;
|
||||
}
|
||||
if (fatal_signal_pending(current))
|
||||
if (signal_pending(current)) {
|
||||
struct ksignal ksig;
|
||||
|
||||
if (!get_signal(&ksig))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
sqt_spin = false;
|
||||
cap_entries = !list_is_singular(&sqd->ctx_list);
|
||||
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
|
||||
@@ -6808,7 +6791,6 @@ static int io_sq_thread(void *data)
|
||||
|
||||
mutex_unlock(&sqd->lock);
|
||||
schedule();
|
||||
try_to_freeze();
|
||||
mutex_lock(&sqd->lock);
|
||||
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
|
||||
io_ring_clear_wakeup_flag(ctx);
|
||||
@@ -6873,7 +6855,7 @@ static int io_run_task_work_sig(void)
|
||||
return 1;
|
||||
if (!signal_pending(current))
|
||||
return 0;
|
||||
if (test_tsk_thread_flag(current, TIF_NOTIFY_SIGNAL))
|
||||
if (test_thread_flag(TIF_NOTIFY_SIGNAL))
|
||||
return -ERESTARTSYS;
|
||||
return -EINTR;
|
||||
}
|
||||
@@ -8563,6 +8545,14 @@ static void io_ring_exit_work(struct work_struct *work)
|
||||
struct io_tctx_node *node;
|
||||
int ret;
|
||||
|
||||
/* prevent SQPOLL from submitting new requests */
|
||||
if (ctx->sq_data) {
|
||||
io_sq_thread_park(ctx->sq_data);
|
||||
list_del_init(&ctx->sqd_list);
|
||||
io_sqd_update_thread_idle(ctx->sq_data);
|
||||
io_sq_thread_unpark(ctx->sq_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're doing polled IO and end up having requests being
|
||||
* submitted async (out-of-line), then completions can come in while
|
||||
@@ -8599,6 +8589,28 @@ static void io_ring_exit_work(struct work_struct *work)
|
||||
io_ring_ctx_free(ctx);
|
||||
}
|
||||
|
||||
/* Returns true if we found and killed one or more timeouts */
|
||||
static bool io_kill_timeouts(struct io_ring_ctx *ctx, struct task_struct *tsk,
|
||||
struct files_struct *files)
|
||||
{
|
||||
struct io_kiocb *req, *tmp;
|
||||
int canceled = 0;
|
||||
|
||||
spin_lock_irq(&ctx->completion_lock);
|
||||
list_for_each_entry_safe(req, tmp, &ctx->timeout_list, timeout.list) {
|
||||
if (io_match_task(req, tsk, files)) {
|
||||
io_kill_timeout(req, -ECANCELED);
|
||||
canceled++;
|
||||
}
|
||||
}
|
||||
io_commit_cqring(ctx);
|
||||
spin_unlock_irq(&ctx->completion_lock);
|
||||
|
||||
if (canceled != 0)
|
||||
io_cqring_ev_posted(ctx);
|
||||
return canceled != 0;
|
||||
}
|
||||
|
||||
static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
|
||||
{
|
||||
unsigned long index;
|
||||
@@ -8614,14 +8626,6 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
|
||||
io_unregister_personality(ctx, index);
|
||||
mutex_unlock(&ctx->uring_lock);
|
||||
|
||||
/* prevent SQPOLL from submitting new requests */
|
||||
if (ctx->sq_data) {
|
||||
io_sq_thread_park(ctx->sq_data);
|
||||
list_del_init(&ctx->sqd_list);
|
||||
io_sqd_update_thread_idle(ctx->sq_data);
|
||||
io_sq_thread_unpark(ctx->sq_data);
|
||||
}
|
||||
|
||||
io_kill_timeouts(ctx, NULL, NULL);
|
||||
io_poll_remove_all(ctx, NULL, NULL);
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ extern void mutex_lock_io(struct mutex *lock);
|
||||
# define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock)
|
||||
# define mutex_lock_killable_nested(lock, subclass) mutex_lock_killable(lock)
|
||||
# define mutex_lock_nest_lock(lock, nest_lock) mutex_lock(lock)
|
||||
# define mutex_lock_io_nested(lock, subclass) mutex_lock(lock)
|
||||
# define mutex_lock_io_nested(lock, subclass) mutex_lock_io(lock)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -1951,8 +1951,14 @@ static __latent_entropy struct task_struct *copy_process(
|
||||
p = dup_task_struct(current, node);
|
||||
if (!p)
|
||||
goto fork_out;
|
||||
if (args->io_thread)
|
||||
if (args->io_thread) {
|
||||
/*
|
||||
* Mark us an IO worker, and block any signal that isn't
|
||||
* fatal or STOP
|
||||
*/
|
||||
p->flags |= PF_IO_WORKER;
|
||||
siginitsetinv(&p->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
||||
}
|
||||
|
||||
cpufreq_task_times_init(p);
|
||||
|
||||
@@ -2443,14 +2449,8 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
|
||||
.stack_size = (unsigned long)arg,
|
||||
.io_thread = 1,
|
||||
};
|
||||
struct task_struct *tsk;
|
||||
|
||||
tsk = copy_process(NULL, 0, node, &args);
|
||||
if (!IS_ERR(tsk)) {
|
||||
sigfillset(&tsk->blocked);
|
||||
sigdelsetmask(&tsk->blocked, sigmask(SIGKILL));
|
||||
}
|
||||
return tsk;
|
||||
return copy_process(NULL, 0, node, &args);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -134,7 +134,7 @@ bool freeze_task(struct task_struct *p)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(p->flags & (PF_KTHREAD | PF_IO_WORKER)))
|
||||
if (!(p->flags & PF_KTHREAD))
|
||||
fake_signal_wake_up(p);
|
||||
else
|
||||
wake_up_state(p, TASK_INTERRUPTIBLE);
|
||||
|
||||
@@ -375,7 +375,7 @@ static int ptrace_attach(struct task_struct *task, long request,
|
||||
audit_ptrace(task);
|
||||
|
||||
retval = -EPERM;
|
||||
if (unlikely(task->flags & (PF_KTHREAD | PF_IO_WORKER)))
|
||||
if (unlikely(task->flags & PF_KTHREAD))
|
||||
goto out;
|
||||
if (same_thread_group(task, current))
|
||||
goto out;
|
||||
|
||||
@@ -91,7 +91,7 @@ static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
|
||||
return true;
|
||||
|
||||
/* Only allow kernel generated signals to this kthread */
|
||||
if (unlikely((t->flags & (PF_KTHREAD | PF_IO_WORKER)) &&
|
||||
if (unlikely((t->flags & PF_KTHREAD) &&
|
||||
(handler == SIG_KTHREAD_KERNEL) && !force))
|
||||
return true;
|
||||
|
||||
@@ -288,8 +288,7 @@ bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask)
|
||||
JOBCTL_STOP_SIGMASK | JOBCTL_TRAPPING));
|
||||
BUG_ON((mask & JOBCTL_TRAPPING) && !(mask & JOBCTL_PENDING_MASK));
|
||||
|
||||
if (unlikely(fatal_signal_pending(task) ||
|
||||
(task->flags & (PF_EXITING | PF_IO_WORKER))))
|
||||
if (unlikely(fatal_signal_pending(task) || (task->flags & PF_EXITING)))
|
||||
return false;
|
||||
|
||||
if (mask & JOBCTL_STOP_SIGMASK)
|
||||
@@ -834,9 +833,6 @@ static int check_kill_permission(int sig, struct kernel_siginfo *info,
|
||||
|
||||
if (!valid_signal(sig))
|
||||
return -EINVAL;
|
||||
/* PF_IO_WORKER threads don't take any signals */
|
||||
if (t->flags & PF_IO_WORKER)
|
||||
return -ESRCH;
|
||||
|
||||
if (!si_fromuser(info))
|
||||
return 0;
|
||||
@@ -1100,7 +1096,7 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
|
||||
/*
|
||||
* Skip useless siginfo allocation for SIGKILL and kernel threads.
|
||||
*/
|
||||
if ((sig == SIGKILL) || (t->flags & (PF_KTHREAD | PF_IO_WORKER)))
|
||||
if ((sig == SIGKILL) || (t->flags & PF_KTHREAD))
|
||||
goto out_set;
|
||||
|
||||
/*
|
||||
@@ -2772,6 +2768,14 @@ relock:
|
||||
do_coredump(&ksig->info);
|
||||
}
|
||||
|
||||
/*
|
||||
* PF_IO_WORKER threads will catch and exit on fatal signals
|
||||
* themselves. They have cleanup that must be performed, so
|
||||
* we cannot call do_exit() on their behalf.
|
||||
*/
|
||||
if (current->flags & PF_IO_WORKER)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Death signals, no core dump.
|
||||
*/
|
||||
@@ -2779,7 +2783,7 @@ relock:
|
||||
/* NOTREACHED */
|
||||
}
|
||||
spin_unlock_irq(&sighand->siglock);
|
||||
|
||||
out:
|
||||
ksig->sig = signr;
|
||||
|
||||
if (!(ksig->ka.sa.sa_flags & SA_EXPOSE_TAGBITS))
|
||||
|
||||
@@ -1154,6 +1154,7 @@ struct kvm_x86_mce {
|
||||
#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0)
|
||||
#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1)
|
||||
#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2)
|
||||
#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3)
|
||||
|
||||
struct kvm_xen_hvm_config {
|
||||
__u32 flags;
|
||||
@@ -1621,12 +1622,24 @@ struct kvm_xen_vcpu_attr {
|
||||
union {
|
||||
__u64 gpa;
|
||||
__u64 pad[8];
|
||||
struct {
|
||||
__u64 state;
|
||||
__u64 state_entry_time;
|
||||
__u64 time_running;
|
||||
__u64 time_runnable;
|
||||
__u64 time_blocked;
|
||||
__u64 time_offline;
|
||||
} runstate;
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
|
||||
#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0
|
||||
#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO 0x1
|
||||
#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR 0x2
|
||||
#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT 0x3
|
||||
#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA 0x4
|
||||
#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
|
||||
|
||||
/* Secure Encrypted Virtualization command */
|
||||
enum sev_cmd_id {
|
||||
|
||||
@@ -402,35 +402,42 @@ static pid_t handle_signalfd(struct daemon *daemon)
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
/*
|
||||
* Take signal fd data as pure signal notification and check all
|
||||
* the sessions state. The reason is that multiple signals can get
|
||||
* coalesced in kernel and we can receive only single signal even
|
||||
* if multiple SIGCHLD were generated.
|
||||
*/
|
||||
err = read(daemon->signal_fd, &si, sizeof(struct signalfd_siginfo));
|
||||
if (err != sizeof(struct signalfd_siginfo))
|
||||
if (err != sizeof(struct signalfd_siginfo)) {
|
||||
pr_err("failed to read signal fd\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_for_each_entry(session, &daemon->sessions, list) {
|
||||
|
||||
if (session->pid != (int) si.ssi_pid)
|
||||
if (session->pid == -1)
|
||||
continue;
|
||||
|
||||
pid = waitpid(session->pid, &status, 0);
|
||||
if (pid == session->pid) {
|
||||
if (WIFEXITED(status)) {
|
||||
pr_info("session '%s' exited, status=%d\n",
|
||||
session->name, WEXITSTATUS(status));
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
pr_info("session '%s' killed (signal %d)\n",
|
||||
session->name, WTERMSIG(status));
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
pr_info("session '%s' stopped (signal %d)\n",
|
||||
session->name, WSTOPSIG(status));
|
||||
} else {
|
||||
pr_info("session '%s' Unexpected status (0x%x)\n",
|
||||
session->name, status);
|
||||
}
|
||||
pid = waitpid(session->pid, &status, WNOHANG);
|
||||
if (pid <= 0)
|
||||
continue;
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
pr_info("session '%s' exited, status=%d\n",
|
||||
session->name, WEXITSTATUS(status));
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
pr_info("session '%s' killed (signal %d)\n",
|
||||
session->name, WTERMSIG(status));
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
pr_info("session '%s' stopped (signal %d)\n",
|
||||
session->name, WSTOPSIG(status));
|
||||
} else {
|
||||
pr_info("session '%s' Unexpected status (0x%x)\n",
|
||||
session->name, status);
|
||||
}
|
||||
|
||||
session->state = KILL;
|
||||
session->pid = -1;
|
||||
return pid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -443,7 +450,6 @@ static int daemon_session__wait(struct daemon_session *session, struct daemon *d
|
||||
.fd = daemon->signal_fd,
|
||||
.events = POLLIN,
|
||||
};
|
||||
pid_t wpid = 0, pid = session->pid;
|
||||
time_t start;
|
||||
|
||||
start = time(NULL);
|
||||
@@ -452,7 +458,7 @@ static int daemon_session__wait(struct daemon_session *session, struct daemon *d
|
||||
int err = poll(&pollfd, 1, 1000);
|
||||
|
||||
if (err > 0) {
|
||||
wpid = handle_signalfd(daemon);
|
||||
handle_signalfd(daemon);
|
||||
} else if (err < 0) {
|
||||
perror("failed: poll\n");
|
||||
return -1;
|
||||
@@ -460,7 +466,7 @@ static int daemon_session__wait(struct daemon_session *session, struct daemon *d
|
||||
|
||||
if (start + secs < time(NULL))
|
||||
return -1;
|
||||
} while (wpid != pid);
|
||||
} while (session->pid != -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -902,7 +908,9 @@ static void daemon_session__kill(struct daemon_session *session,
|
||||
daemon_session__signal(session, SIGKILL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
pr_err("failed to wait for session %s\n",
|
||||
session->name);
|
||||
return;
|
||||
}
|
||||
how++;
|
||||
|
||||
@@ -955,7 +963,8 @@ static void daemon__kill(struct daemon *daemon)
|
||||
daemon__signal(daemon, SIGKILL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
pr_err("failed to wait for sessions\n");
|
||||
return;
|
||||
}
|
||||
how++;
|
||||
|
||||
@@ -1344,7 +1353,7 @@ out:
|
||||
close(sock_fd);
|
||||
if (conf_fd != -1)
|
||||
close(conf_fd);
|
||||
if (conf_fd != -1)
|
||||
if (signal_fd != -1)
|
||||
close(signal_fd);
|
||||
|
||||
pr_info("daemon exited\n");
|
||||
|
||||
@@ -86,7 +86,7 @@ static struct {
|
||||
.msg_load_fail = "check your vmlinux setting?",
|
||||
.target_func = &epoll_pwait_loop,
|
||||
.expect_result = (NR_ITERS + 1) / 2,
|
||||
.pin = true,
|
||||
.pin = true,
|
||||
},
|
||||
#ifdef HAVE_BPF_PROLOGUE
|
||||
{
|
||||
@@ -99,13 +99,6 @@ static struct {
|
||||
.expect_result = (NR_ITERS + 1) / 4,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.prog_id = LLVM_TESTCASE_BPF_RELOCATION,
|
||||
.desc = "BPF relocation checker",
|
||||
.name = "[bpf_relocation_test]",
|
||||
.msg_compile_fail = "fix 'perf test LLVM' first",
|
||||
.msg_load_fail = "libbpf error when dealing with relocation",
|
||||
},
|
||||
};
|
||||
|
||||
static int do_test(struct bpf_object *obj, int (*func)(void),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# daemon operations
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
|
||||
@@ -298,10 +298,6 @@ static int auxtrace_queues__queue_buffer(struct auxtrace_queues *queues,
|
||||
queue->set = true;
|
||||
queue->tid = buffer->tid;
|
||||
queue->cpu = buffer->cpu;
|
||||
} else if (buffer->cpu != queue->cpu || buffer->tid != queue->tid) {
|
||||
pr_err("auxtrace queue conflict: cpu %d, tid %d vs cpu %d, tid %d\n",
|
||||
queue->cpu, queue->tid, buffer->cpu, buffer->tid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buffer->buffer_nr = queues->next_buffer_nr++;
|
||||
|
||||
@@ -196,25 +196,32 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
|
||||
}
|
||||
|
||||
if (info_linear->info_len < offsetof(struct bpf_prog_info, prog_tags)) {
|
||||
free(info_linear);
|
||||
pr_debug("%s: the kernel is too old, aborting\n", __func__);
|
||||
return -2;
|
||||
}
|
||||
|
||||
info = &info_linear->info;
|
||||
if (!info->jited_ksyms) {
|
||||
free(info_linear);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* number of ksyms, func_lengths, and tags should match */
|
||||
sub_prog_cnt = info->nr_jited_ksyms;
|
||||
if (sub_prog_cnt != info->nr_prog_tags ||
|
||||
sub_prog_cnt != info->nr_jited_func_lens)
|
||||
sub_prog_cnt != info->nr_jited_func_lens) {
|
||||
free(info_linear);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check BTF func info support */
|
||||
if (info->btf_id && info->nr_func_info && info->func_info_rec_size) {
|
||||
/* btf func info number should be same as sub_prog_cnt */
|
||||
if (sub_prog_cnt != info->nr_func_info) {
|
||||
pr_debug("%s: mismatch in BPF sub program count and BTF function info count, aborting\n", __func__);
|
||||
err = -1;
|
||||
goto out;
|
||||
free(info_linear);
|
||||
return -1;
|
||||
}
|
||||
if (btf__get_from_id(info->btf_id, &btf)) {
|
||||
pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info->btf_id);
|
||||
|
||||
@@ -356,6 +356,9 @@ __add_event(struct list_head *list, int *idx,
|
||||
struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) :
|
||||
cpu_list ? perf_cpu_map__new(cpu_list) : NULL;
|
||||
|
||||
if (pmu && attr->type == PERF_TYPE_RAW)
|
||||
perf_pmu__warn_invalid_config(pmu, attr->config, name);
|
||||
|
||||
if (init_attr)
|
||||
event_attr_init(attr);
|
||||
|
||||
|
||||
@@ -1812,3 +1812,36 @@ int perf_pmu__caps_parse(struct perf_pmu *pmu)
|
||||
|
||||
return nr_caps;
|
||||
}
|
||||
|
||||
void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
|
||||
char *name)
|
||||
{
|
||||
struct perf_pmu_format *format;
|
||||
__u64 masks = 0, bits;
|
||||
char buf[100];
|
||||
unsigned int i;
|
||||
|
||||
list_for_each_entry(format, &pmu->format, list) {
|
||||
if (format->value != PERF_PMU_FORMAT_VALUE_CONFIG)
|
||||
continue;
|
||||
|
||||
for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS)
|
||||
masks |= 1ULL << i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Kernel doesn't export any valid format bits.
|
||||
*/
|
||||
if (masks == 0)
|
||||
return;
|
||||
|
||||
bits = config & ~masks;
|
||||
if (bits == 0)
|
||||
return;
|
||||
|
||||
bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf));
|
||||
|
||||
pr_warning("WARNING: event '%s' not valid (bits %s of config "
|
||||
"'%llx' not supported by kernel)!\n",
|
||||
name ?: "N/A", buf, config);
|
||||
}
|
||||
|
||||
@@ -123,4 +123,7 @@ int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
|
||||
|
||||
int perf_pmu__caps_parse(struct perf_pmu *pmu);
|
||||
|
||||
void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
|
||||
char *name);
|
||||
|
||||
#endif /* __PMU_H */
|
||||
|
||||
@@ -424,7 +424,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
|
||||
|
||||
while (!io.eof) {
|
||||
static const char anonstr[] = "//anon";
|
||||
size_t size;
|
||||
size_t size, aligned_size;
|
||||
|
||||
/* ensure null termination since stack will be reused. */
|
||||
event->mmap2.filename[0] = '\0';
|
||||
@@ -484,11 +484,12 @@ out:
|
||||
}
|
||||
|
||||
size = strlen(event->mmap2.filename) + 1;
|
||||
size = PERF_ALIGN(size, sizeof(u64));
|
||||
aligned_size = PERF_ALIGN(size, sizeof(u64));
|
||||
event->mmap2.len -= event->mmap.start;
|
||||
event->mmap2.header.size = (sizeof(event->mmap2) -
|
||||
(sizeof(event->mmap2.filename) - size));
|
||||
memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
|
||||
(sizeof(event->mmap2.filename) - aligned_size));
|
||||
memset(event->mmap2.filename + size, 0, machine->id_hdr_size +
|
||||
(aligned_size - size));
|
||||
event->mmap2.header.size += machine->id_hdr_size;
|
||||
event->mmap2.pid = tgid;
|
||||
event->mmap2.tid = pid;
|
||||
@@ -758,7 +759,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
|
||||
for (i = 0; i < n; i++) {
|
||||
char *end;
|
||||
pid_t _pid;
|
||||
bool kernel_thread;
|
||||
bool kernel_thread = false;
|
||||
|
||||
_pid = strtol(dirent[i]->d_name, &end, 10);
|
||||
if (*end)
|
||||
|
||||
@@ -133,6 +133,8 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *s
|
||||
if (dso != NULL) {
|
||||
__dsos__add(&machine->dsos, dso);
|
||||
dso__set_long_name(dso, long_name, false);
|
||||
/* Put dso here because __dsos_add already got it */
|
||||
dso__put(dso);
|
||||
}
|
||||
|
||||
return dso;
|
||||
|
||||
Reference in New Issue
Block a user