From patchwork Wed Nov 28 14:23:44 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 1816711 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 067ECDF26F for ; Wed, 28 Nov 2012 14:24:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755255Ab2K1OYI (ORCPT ); Wed, 28 Nov 2012 09:24:08 -0500 Received: from mail-la0-f46.google.com ([209.85.215.46]:51507 "EHLO mail-la0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754738Ab2K1OYH (ORCPT ); Wed, 28 Nov 2012 09:24:07 -0500 Received: by mail-la0-f46.google.com with SMTP id p5so7739580lag.19 for ; Wed, 28 Nov 2012 06:24:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=UnH84tCNsT6BKQJW5qHnUzqZmnXfxo+w7gmg0O1Cf/s=; b=GoMNqesRlGjZPyrFsVrpaj9NJ8wx735jKLWdbWtrpnrUvMpSEsdo2CHFl72rAchXXD yt+Zc29aEGDRstSVLogUJye5Qleo7fsHcTHGXLuD46aW118UqzMg1/9wGdIn/lmXjkGK XJVKtwCSXnpaBr9NC7M1fOHJhP8vffrEwm1AZkUIEFNo3ramA/mnCAsv38Nyfd3mAMBR 8VoAXdRAvhBGFtOsmoy0gHONCxM5Un3V+zFybNb9kiCUxbXyBMo7QsW3SlZ6li9gWVFg 5TetZc0hrqpYoqr56bu7ahkIhk6x/mOlH0kUI1VGGC+A7UnwxUdZMc6fUjVz0zVOvRkb NFDA== Received: by 10.152.106.171 with SMTP id gv11mr18527362lab.26.1354112645657; Wed, 28 Nov 2012 06:24:05 -0800 (PST) Received: from localhost.localdomain ([95.84.0.69]) by mx.google.com with ESMTPS id oj5sm8159019lab.8.2012.11.28.06.24.04 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 28 Nov 2012 06:24:04 -0800 (PST) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [PATCH v2 5/6] CIFS: Do not permit write to a range mandatory locked with a read lock Date: Wed, 28 Nov 2012 18:23:44 +0400 Message-Id: <1354112625-30315-6-git-send-email-piastry@etersoft.ru> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1354112625-30315-1-git-send-email-piastry@etersoft.ru> References: <1354112625-30315-1-git-send-email-piastry@etersoft.ru> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org We don't need to permit a write to the area locked with a read lock by any process including the process that issues the write. Signed-off-by: Pavel Shilovsky Reviewed-by: Jeff Layton --- fs/cifs/cifsproto.h | 2 +- fs/cifs/file.c | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7e1562d..4883f95 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -187,7 +187,7 @@ extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon); extern bool cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length, __u8 type, struct cifsLockInfo **conf_lock, - bool rw_check); + int rw_check); extern void cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink, struct cifs_pending_open *open); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index f8fe1bd..e7fc39c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -765,10 +765,15 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock) } } +#define CIFS_LOCK_OP 0 +#define CIFS_READ_OP 1 +#define CIFS_WRITE_OP 2 + +/* @rw_check : 0 - no op, 1 - read, 2 - write */ static bool cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset, __u64 length, __u8 type, struct cifsFileInfo *cfile, - struct cifsLockInfo **conf_lock, bool rw_check) + struct cifsLockInfo **conf_lock, int rw_check) { struct cifsLockInfo *li; struct cifsFileInfo *cur_cfile = fdlocks->cfile; @@ -778,9 +783,13 @@ cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset, if (offset + length <= li->offset || offset >= li->offset + li->length) continue; - if (rw_check && server->ops->compare_fids(cfile, cur_cfile) && - current->tgid == li->pid) - continue; + if (rw_check != CIFS_LOCK_OP && current->tgid == li->pid && + server->ops->compare_fids(cfile, cur_cfile)) { + /* shared lock prevents write op through the same fid */ + if (!(li->type & server->vals->shared_lock_type) || + rw_check != CIFS_WRITE_OP) + continue; + } if ((type & server->vals->shared_lock_type) && ((server->ops->compare_fids(cfile, cur_cfile) && current->tgid == li->pid) || type == li->type)) @@ -795,7 +804,7 @@ cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset, bool cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length, __u8 type, struct cifsLockInfo **conf_lock, - bool rw_check) + int rw_check) { bool rc = false; struct cifs_fid_locks *cur; @@ -831,7 +840,7 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, down_read(&cinode->lock_sem); exist = cifs_find_lock_conflict(cfile, offset, length, type, - &conf_lock, false); + &conf_lock, CIFS_LOCK_OP); if (exist) { flock->fl_start = conf_lock->offset; flock->fl_end = conf_lock->offset + conf_lock->length - 1; @@ -878,7 +887,7 @@ try_again: down_write(&cinode->lock_sem); exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, - lock->type, &conf_lock, false); + lock->type, &conf_lock, CIFS_LOCK_OP); if (!exist && cinode->can_cache_brlcks) { list_add_tail(&lock->llist, &cfile->llist->locks); up_write(&cinode->lock_sem); @@ -2472,7 +2481,7 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, down_read(&cinode->lock_sem); if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs), server->vals->exclusive_lock_type, NULL, - true)) { + CIFS_WRITE_OP)) { mutex_lock(&inode->i_mutex); rc = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); @@ -2907,7 +2916,7 @@ cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, down_read(&cinode->lock_sem); if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs), tcon->ses->server->vals->shared_lock_type, - NULL, true)) + NULL, CIFS_READ_OP)) rc = generic_file_aio_read(iocb, iov, nr_segs, pos); up_read(&cinode->lock_sem); return rc;