From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754686AbdCTNGO (ORCPT ); Mon, 20 Mar 2017 09:06:14 -0400 Received: from mga14.intel.com ([192.55.52.115]:42966 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753395AbdCTNFe (ORCPT ); Mon, 20 Mar 2017 09:05:34 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,194,1486454400"; d="scan'208";a="78970110" From: Tomas Winkler To: Greg Kroah-Hartman Cc: Alexander Usyskin , linux-kernel@vger.kernel.org, Tomas Winkler Subject: [char-misc-next 5/5] mei: implement fsync Date: Mon, 20 Mar 2017 15:04:06 +0200 Message-Id: <20170320130406.11120-5-tomas.winkler@intel.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170320130406.11120-1-tomas.winkler@intel.com> References: <20170320130406.11120-1-tomas.winkler@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alexander Usyskin When write() returns successfully, it is only assumed that a message was successfully queued. Add fsync syscall implementation to help user-space ensure that all data is written. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin --- drivers/misc/mei/main.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 9802c5930c10..e825f013e54e 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -586,6 +586,77 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) } /** + * mei_cl_is_write_queued - check if the client has pending writes. + * + * @cl: writing host client + * + * Return: true if client is writing, false otherwise. + */ +static bool mei_cl_is_write_queued(struct mei_cl *cl) +{ + struct mei_device *dev = cl->dev; + struct mei_cl_cb *cb; + + list_for_each_entry(cb, &dev->write_list, list) + if (cb->cl == cl) + return true; + list_for_each_entry(cb, &dev->write_waiting_list, list) + if (cb->cl == cl) + return true; + return false; +} + +/** + * mei_fsync - the fsync handler + * + * @fp: pointer to file structure + * @start: unused + * @end: unused + * @datasync: unused + * + * Return: 0 on success, -ENODEV if client is not connected + */ +static int mei_fsync(struct file *fp, loff_t start, loff_t end, int datasync) +{ + struct mei_cl *cl = fp->private_data; + struct mei_device *dev; + int rets; + + if (WARN_ON(!cl || !cl->dev)) + return -ENODEV; + + dev = cl->dev; + + mutex_lock(&dev->device_lock); + + if (dev->dev_state != MEI_DEV_ENABLED || !mei_cl_is_connected(cl)) { + rets = -ENODEV; + goto out; + } + + while (mei_cl_is_write_queued(cl)) { + mutex_unlock(&dev->device_lock); + rets = wait_event_interruptible(cl->tx_wait, + cl->writing_state == MEI_WRITE_COMPLETE || + !mei_cl_is_connected(cl)); + mutex_lock(&dev->device_lock); + if (rets) { + if (signal_pending(current)) + rets = -EINTR; + goto out; + } + if (!mei_cl_is_connected(cl)) { + rets = -ENODEV; + goto out; + } + } + rets = 0; +out: + mutex_unlock(&dev->device_lock); + return rets; +} + +/** * mei_fasync - asynchronous io support * * @fd: file descriptor @@ -700,6 +771,7 @@ static const struct file_operations mei_fops = { .release = mei_release, .write = mei_write, .poll = mei_poll, + .fsync = mei_fsync, .fasync = mei_fasync, .llseek = no_llseek }; -- 2.9.3