From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 8B40D139694 for ; Mon, 8 May 2017 10:45:06 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id D4E41E0DE1; Mon, 8 May 2017 10:45:05 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id A8788E0DE1 for ; Mon, 8 May 2017 10:45:05 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 5D20634071C for ; Mon, 8 May 2017 10:45:04 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 257502494 for ; Mon, 8 May 2017 10:45:03 +0000 (UTC) From: "Mike Pagano" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Pagano" Message-ID: <1494240293.7287b48d4c0fe338c20e0ef320c23a4b2376c81c.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:4.10 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1014_linux-4.10.15.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: 7287b48d4c0fe338c20e0ef320c23a4b2376c81c X-VCS-Branch: 4.10 Date: Mon, 8 May 2017 10:45:03 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 8c259e3e-6ac5-4953-81ad-2e221ed6ea8b X-Archives-Hash: bc954378c4e305d78b336cb39d0427c5 commit: 7287b48d4c0fe338c20e0ef320c23a4b2376c81c Author: Mike Pagano gentoo org> AuthorDate: Mon May 8 10:44:53 2017 +0000 Commit: Mike Pagano gentoo org> CommitDate: Mon May 8 10:44:53 2017 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=7287b48d Linux patch 4.10.15 0000_README | 4 + 1014_linux-4.10.15.patch | 509 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 513 insertions(+) diff --git a/0000_README b/0000_README index 5295a7d..1e8afc8 100644 --- a/0000_README +++ b/0000_README @@ -99,6 +99,10 @@ Patch: 1013_linux-4.10.14.patch From: http://www.kernel.org Desc: Linux 4.10.14 +Patch: 1014_linux-4.10.15.patch +From: http://www.kernel.org +Desc: Linux 4.10.15 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1014_linux-4.10.15.patch b/1014_linux-4.10.15.patch new file mode 100644 index 0000000..d485ffb --- /dev/null +++ b/1014_linux-4.10.15.patch @@ -0,0 +1,509 @@ +diff --git a/Makefile b/Makefile +index 48756653c42c..6f600fee5753 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 10 +-SUBLEVEL = 14 ++SUBLEVEL = 15 + EXTRAVERSION = + NAME = Fearless Coyote + +diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c +index 43146162c122..b99c1df48156 100644 +--- a/drivers/hwmon/it87.c ++++ b/drivers/hwmon/it87.c +@@ -3115,7 +3115,7 @@ static int __init sm_it87_init(void) + { + int sioaddr[2] = { REG_2E, REG_4E }; + struct it87_sio_data sio_data; +- unsigned short isa_address; ++ unsigned short isa_address[2]; + bool found = false; + int i, err; + +@@ -3125,15 +3125,29 @@ static int __init sm_it87_init(void) + + for (i = 0; i < ARRAY_SIZE(sioaddr); i++) { + memset(&sio_data, 0, sizeof(struct it87_sio_data)); +- isa_address = 0; +- err = it87_find(sioaddr[i], &isa_address, &sio_data); +- if (err || isa_address == 0) ++ isa_address[i] = 0; ++ err = it87_find(sioaddr[i], &isa_address[i], &sio_data); ++ if (err || isa_address[i] == 0) + continue; ++ /* ++ * Don't register second chip if its ISA address matches ++ * the first chip's ISA address. ++ */ ++ if (i && isa_address[i] == isa_address[0]) ++ break; + +- err = it87_device_add(i, isa_address, &sio_data); ++ err = it87_device_add(i, isa_address[i], &sio_data); + if (err) + goto exit_dev_unregister; ++ + found = true; ++ ++ /* ++ * IT8705F may respond on both SIO addresses. ++ * Stop probing after finding one. ++ */ ++ if (sio_data.type == it87) ++ break; + } + + if (!found) { +diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c +index a5a9b17f0f7f..5edc2a58edcc 100644 +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1847,7 +1847,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user) + if (r) + goto out; + +- param->data_size = sizeof(*param); ++ param->data_size = offsetof(struct dm_ioctl, data); + r = fn(param, input_param_size); + + if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) && +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index 7be04fc0d0e7..6f5d173ea9ff 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -400,8 +400,6 @@ MODULE_PARM_DESC(storvsc_vcpus_per_sub_channel, "Ratio of VCPUs to subchannels") + */ + static int storvsc_timeout = 180; + +-static int msft_blist_flags = BLIST_TRY_VPD_PAGES; +- + #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) + static struct scsi_transport_template *fc_transport_template; + #endif +@@ -1283,6 +1281,22 @@ static int storvsc_do_io(struct hv_device *device, + return ret; + } + ++static int storvsc_device_alloc(struct scsi_device *sdevice) ++{ ++ /* ++ * Set blist flag to permit the reading of the VPD pages even when ++ * the target may claim SPC-2 compliance. MSFT targets currently ++ * claim SPC-2 compliance while they implement post SPC-2 features. ++ * With this flag we can correctly handle WRITE_SAME_16 issues. ++ * ++ * Hypervisor reports SCSI_UNKNOWN type for DVD ROM device but ++ * still supports REPORT LUN. ++ */ ++ sdevice->sdev_bflags = BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES; ++ ++ return 0; ++} ++ + static int storvsc_device_configure(struct scsi_device *sdevice) + { + +@@ -1298,14 +1312,6 @@ static int storvsc_device_configure(struct scsi_device *sdevice) + sdevice->no_write_same = 1; + + /* +- * Add blist flags to permit the reading of the VPD pages even when +- * the target may claim SPC-2 compliance. MSFT targets currently +- * claim SPC-2 compliance while they implement post SPC-2 features. +- * With this patch we can correctly handle WRITE_SAME_16 issues. +- */ +- sdevice->sdev_bflags |= msft_blist_flags; +- +- /* + * If the host is WIN8 or WIN8 R2, claim conformance to SPC-3 + * if the device is a MSFT virtual device. If the host is + * WIN10 or newer, allow write_same. +@@ -1569,6 +1575,7 @@ static struct scsi_host_template scsi_driver = { + .eh_host_reset_handler = storvsc_host_reset_handler, + .proc_name = "storvsc_host", + .eh_timed_out = storvsc_eh_timed_out, ++ .slave_alloc = storvsc_device_alloc, + .slave_configure = storvsc_device_configure, + .cmd_per_lun = 255, + .this_id = -1, +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 54a7d078a3a8..7fa45f48e59d 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -241,6 +241,7 @@ struct smb_version_operations { + /* verify the message */ + int (*check_message)(char *, unsigned int, struct TCP_Server_Info *); + bool (*is_oplock_break)(char *, struct TCP_Server_Info *); ++ int (*handle_cancelled_mid)(char *, struct TCP_Server_Info *); + void (*downgrade_oplock)(struct TCP_Server_Info *, + struct cifsInodeInfo *, bool); + /* process transaction2 response */ +@@ -1318,12 +1319,19 @@ struct mid_q_entry { + void *callback_data; /* general purpose pointer for callback */ + void *resp_buf; /* pointer to received SMB header */ + int mid_state; /* wish this were enum but can not pass to wait_event */ ++ unsigned int mid_flags; + __le16 command; /* smb command code */ + bool large_buf:1; /* if valid response, is pointer to large buf */ + bool multiRsp:1; /* multiple trans2 responses for one request */ + bool multiEnd:1; /* both received */ + }; + ++struct close_cancelled_open { ++ struct cifs_fid fid; ++ struct cifs_tcon *tcon; ++ struct work_struct work; ++}; ++ + /* Make code in transport.c a little cleaner by moving + update of optional stats into function below */ + #ifdef CONFIG_CIFS_STATS2 +@@ -1455,6 +1463,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, + #define MID_RESPONSE_MALFORMED 0x10 + #define MID_SHUTDOWN 0x20 + ++/* Flags */ ++#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */ ++ + /* Types of response buffer returned from SendReceive2 */ + #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ + #define CIFS_SMALL_BUFFER 1 +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index b47261858e6d..2dc92351027b 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1423,6 +1423,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) + + length = discard_remaining_data(server); + dequeue_mid(mid, rdata->result); ++ mid->resp_buf = server->smallbuf; ++ server->smallbuf = NULL; + return length; + } + +@@ -1534,6 +1536,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) + return cifs_readv_discard(server, mid); + + dequeue_mid(mid, false); ++ mid->resp_buf = server->smallbuf; ++ server->smallbuf = NULL; + return length; + } + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 35ae49ed1f76..acf7bc1eab77 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -887,10 +887,19 @@ cifs_demultiplex_thread(void *p) + + server->lstrp = jiffies; + if (mid_entry != NULL) { ++ if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && ++ mid_entry->mid_state == MID_RESPONSE_RECEIVED && ++ server->ops->handle_cancelled_mid) ++ server->ops->handle_cancelled_mid( ++ mid_entry->resp_buf, ++ server); ++ + if (!mid_entry->multiRsp || mid_entry->multiEnd) + mid_entry->callback(mid_entry); +- } else if (!server->ops->is_oplock_break || +- !server->ops->is_oplock_break(buf, server)) { ++ } else if (server->ops->is_oplock_break && ++ server->ops->is_oplock_break(buf, server)) { ++ cifs_dbg(FYI, "Received oplock break\n"); ++ } else { + cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n", + atomic_read(&midCount)); + cifs_dump_mem("Received Data is: ", buf, +diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c +index 3d383489b9cf..97307808ae42 100644 +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -654,3 +654,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) + cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n"); + return false; + } ++ ++void ++smb2_cancelled_close_fid(struct work_struct *work) ++{ ++ struct close_cancelled_open *cancelled = container_of(work, ++ struct close_cancelled_open, work); ++ ++ cifs_dbg(VFS, "Close unmatched open\n"); ++ ++ SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, ++ cancelled->fid.volatile_fid); ++ cifs_put_tcon(cancelled->tcon); ++ kfree(cancelled); ++} ++ ++int ++smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) ++{ ++ struct smb2_hdr *hdr = (struct smb2_hdr *)buffer; ++ struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; ++ struct cifs_tcon *tcon; ++ struct close_cancelled_open *cancelled; ++ ++ if (hdr->Command != SMB2_CREATE || hdr->Status != STATUS_SUCCESS) ++ return 0; ++ ++ cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL); ++ if (!cancelled) ++ return -ENOMEM; ++ ++ tcon = smb2_find_smb_tcon(server, hdr->SessionId, hdr->TreeId); ++ if (!tcon) { ++ kfree(cancelled); ++ return -ENOENT; ++ } ++ ++ cancelled->fid.persistent_fid = rsp->PersistentFileId; ++ cancelled->fid.volatile_fid = rsp->VolatileFileId; ++ cancelled->tcon = tcon; ++ INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); ++ queue_work(cifsiod_wq, &cancelled->work); ++ ++ return 0; ++} +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 5d456ebb3813..007abf7195af 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1565,6 +1565,7 @@ struct smb_version_operations smb20_operations = { + .clear_stats = smb2_clear_stats, + .print_stats = smb2_print_stats, + .is_oplock_break = smb2_is_valid_oplock_break, ++ .handle_cancelled_mid = smb2_handle_cancelled_mid, + .downgrade_oplock = smb2_downgrade_oplock, + .need_neg = smb2_need_neg, + .negotiate = smb2_negotiate, +@@ -1645,6 +1646,7 @@ struct smb_version_operations smb21_operations = { + .clear_stats = smb2_clear_stats, + .print_stats = smb2_print_stats, + .is_oplock_break = smb2_is_valid_oplock_break, ++ .handle_cancelled_mid = smb2_handle_cancelled_mid, + .downgrade_oplock = smb2_downgrade_oplock, + .need_neg = smb2_need_neg, + .negotiate = smb2_negotiate, +@@ -1727,6 +1729,7 @@ struct smb_version_operations smb30_operations = { + .print_stats = smb2_print_stats, + .dump_share_caps = smb2_dump_share_caps, + .is_oplock_break = smb2_is_valid_oplock_break, ++ .handle_cancelled_mid = smb2_handle_cancelled_mid, + .downgrade_oplock = smb2_downgrade_oplock, + .need_neg = smb2_need_neg, + .negotiate = smb2_negotiate, +@@ -1815,6 +1818,7 @@ struct smb_version_operations smb311_operations = { + .print_stats = smb2_print_stats, + .dump_share_caps = smb2_dump_share_caps, + .is_oplock_break = smb2_is_valid_oplock_break, ++ .handle_cancelled_mid = smb2_handle_cancelled_mid, + .downgrade_oplock = smb2_downgrade_oplock, + .need_neg = smb2_need_neg, + .negotiate = smb2_negotiate, +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index f2d511a6971b..04ef6e914597 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -48,6 +48,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses, + struct smb_rqst *rqst); + extern struct mid_q_entry *smb2_setup_async_request( + struct TCP_Server_Info *server, struct smb_rqst *rqst); ++extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server, ++ __u64 ses_id); ++extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, ++ __u64 ses_id, __u32 tid); + extern int smb2_calc_signature(struct smb_rqst *rqst, + struct TCP_Server_Info *server); + extern int smb3_calc_signature(struct smb_rqst *rqst, +@@ -158,6 +162,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, + extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, + const u64 persistent_fid, const u64 volatile_fid, + const __u8 oplock_level); ++extern int smb2_handle_cancelled_mid(char *buffer, ++ struct TCP_Server_Info *server); ++void smb2_cancelled_close_fid(struct work_struct *work); + extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_file_id, u64 volatile_file_id, + struct kstatfs *FSData); +diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c +index bc9a7b634643..390b0d0198f8 100644 +--- a/fs/cifs/smb2transport.c ++++ b/fs/cifs/smb2transport.c +@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server) + } + + static struct cifs_ses * +-smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) ++smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id) + { + struct cifs_ses *ses; + +- spin_lock(&cifs_tcp_ses_lock); + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { +- if (ses->Suid != smb2hdr->SessionId) ++ if (ses->Suid != ses_id) + continue; +- spin_unlock(&cifs_tcp_ses_lock); + return ses; + } ++ ++ return NULL; ++} ++ ++struct cifs_ses * ++smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id) ++{ ++ struct cifs_ses *ses; ++ ++ spin_lock(&cifs_tcp_ses_lock); ++ ses = smb2_find_smb_ses_unlocked(server, ses_id); + spin_unlock(&cifs_tcp_ses_lock); + ++ return ses; ++} ++ ++static struct cifs_tcon * ++smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid) ++{ ++ struct cifs_tcon *tcon; ++ ++ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { ++ if (tcon->tid != tid) ++ continue; ++ ++tcon->tc_count; ++ return tcon; ++ } ++ + return NULL; + } + ++/* ++ * Obtain tcon corresponding to the tid in the given ++ * cifs_ses ++ */ ++ ++struct cifs_tcon * ++smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid) ++{ ++ struct cifs_ses *ses; ++ struct cifs_tcon *tcon; ++ ++ spin_lock(&cifs_tcp_ses_lock); ++ ses = smb2_find_smb_ses_unlocked(server, ses_id); ++ if (!ses) { ++ spin_unlock(&cifs_tcp_ses_lock); ++ return NULL; ++ } ++ tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid); ++ spin_unlock(&cifs_tcp_ses_lock); ++ ++ return tcon; ++} + + int + smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) +@@ -142,7 +188,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; + struct cifs_ses *ses; + +- ses = smb2_find_smb_ses(smb2_pdu, server); ++ ses = smb2_find_smb_ses(server, smb2_pdu->SessionId); + if (!ses) { + cifs_dbg(VFS, "%s: Could not find session\n", __func__); + return 0; +@@ -359,7 +405,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; + struct cifs_ses *ses; + +- ses = smb2_find_smb_ses(smb2_pdu, server); ++ ses = smb2_find_smb_ses(server, smb2_pdu->SessionId); + if (!ses) { + cifs_dbg(VFS, "%s: Could not find session\n", __func__); + return 0; +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index fbb84c08e3cd..842e6a042023 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -728,9 +728,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, + + rc = wait_for_response(ses->server, midQ); + if (rc != 0) { ++ cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid); + send_cancel(ses->server, buf, midQ); + spin_lock(&GlobalMid_Lock); + if (midQ->mid_state == MID_REQUEST_SUBMITTED) { ++ midQ->mid_flags |= MID_WAIT_CANCELLED; + midQ->callback = DeleteMidQEntry; + spin_unlock(&GlobalMid_Lock); + cifs_small_buf_release(buf); +diff --git a/fs/timerfd.c b/fs/timerfd.c +index c173cc196175..384fa759a563 100644 +--- a/fs/timerfd.c ++++ b/fs/timerfd.c +@@ -40,6 +40,7 @@ struct timerfd_ctx { + short unsigned settime_flags; /* to show in fdinfo */ + struct rcu_head rcu; + struct list_head clist; ++ spinlock_t cancel_lock; + bool might_cancel; + }; + +@@ -112,7 +113,7 @@ void timerfd_clock_was_set(void) + rcu_read_unlock(); + } + +-static void timerfd_remove_cancel(struct timerfd_ctx *ctx) ++static void __timerfd_remove_cancel(struct timerfd_ctx *ctx) + { + if (ctx->might_cancel) { + ctx->might_cancel = false; +@@ -122,6 +123,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx) + } + } + ++static void timerfd_remove_cancel(struct timerfd_ctx *ctx) ++{ ++ spin_lock(&ctx->cancel_lock); ++ __timerfd_remove_cancel(ctx); ++ spin_unlock(&ctx->cancel_lock); ++} ++ + static bool timerfd_canceled(struct timerfd_ctx *ctx) + { + if (!ctx->might_cancel || ctx->moffs != KTIME_MAX) +@@ -132,6 +140,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx) + + static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) + { ++ spin_lock(&ctx->cancel_lock); + if ((ctx->clockid == CLOCK_REALTIME || + ctx->clockid == CLOCK_REALTIME_ALARM) && + (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) { +@@ -141,9 +150,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) + list_add_rcu(&ctx->clist, &cancel_list); + spin_unlock(&cancel_lock); + } +- } else if (ctx->might_cancel) { +- timerfd_remove_cancel(ctx); ++ } else { ++ __timerfd_remove_cancel(ctx); + } ++ spin_unlock(&ctx->cancel_lock); + } + + static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) +@@ -400,6 +410,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) + return -ENOMEM; + + init_waitqueue_head(&ctx->wqh); ++ spin_lock_init(&ctx->cancel_lock); + ctx->clockid = clockid; + + if (isalarm(ctx))