From: Jeff Layton <jlayton@redhat.com>
To: linux-fsdevel@vger.kernel.org
Cc: nfs-ganesha-devel@lists.sourceforge.net,
samba-technical@lists.samba.org, linux-kernel@vger.kernel.org
Subject: [PATCH v4 13/13] locks: add new "private" lock type that is owned by the filp
Date: Thu, 19 Dec 2013 08:34:25 -0500 [thread overview]
Message-ID: <1387460065-28269-14-git-send-email-jlayton@redhat.com> (raw)
In-Reply-To: <1387460065-28269-1-git-send-email-jlayton@redhat.com>
Due to some unfortunate history, POSIX locks have very strange and
unhelpful semantics. The thing that usually catches people by surprise
is that they are dropped whenever the process closes any file descriptor
associated with the inode.
This is extremely problematic for people developing file servers that
need to implement byte-range locks. Developers often need a "lock
management" facility to ensure that file descriptors are not closed
until all of the locks associated with the inode are finished.
Additionally, "classic" POSIX locks are owned by the process. Locks
taken between threads within the same process won't conflict with one
another, which renders them useless for synchronization between threads.
This patchset adds a new type of lock that attempts to address these
issues. These locks conflict with classic POSIX read/write locks, but
have semantics that are more like BSD locks with respect to inheritance
and behavior on close.
This is implemented primarily by changing how fl_owner field is set for
these locks. Instead of having them owned by the files_struct of the
process, they are instead owned by the filp on which they were acquired.
Thus, they are inherited across fork() and are only released when the
last reference to a filp is put.
These new semantics prevent them from being merged with classic POSIX
locks, even if they are acquired by the same process. These locks will
also conflict with classic POSIX locks even if they are acquired by
the same process or on the same file descriptor.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 34 ++++++++++++++++++++++++++++++++--
include/uapi/asm-generic/fcntl.h | 16 ++++++++++++++++
2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 013b177..bd2d824 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -381,7 +381,6 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
} else
fl->fl_end = OFFSET_MAX;
- fl->fl_owner = current->files;
fl->fl_pid = current->tgid;
fl->fl_file = filp;
fl->fl_flags = FL_POSIX;
@@ -391,16 +390,45 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
/* Ensure that fl->fl_filp has compatible f_mode */
switch (l->l_type) {
case F_RDLCK:
+ case F_RDLCKP:
if (!(filp->f_mode & FMODE_READ))
return -EBADF;
break;
case F_WRLCK:
+ case F_WRLCKP:
if (!(filp->f_mode & FMODE_WRITE))
return -EBADF;
break;
}
- return assign_type(fl, l->l_type);
+ /*
+ * FL_FILE_PVT locks are "owned" by the filp upon which they were
+ * acquired, regardless of what task is dealing with them. Set the
+ * fl_owner appropriately and flag them as private.
+ */
+ switch(l->l_type) {
+ case F_RDLCKP:
+ fl->fl_owner = (fl_owner_t)filp;
+ fl->fl_type = F_RDLCK;
+ fl->fl_flags |= FL_FILE_PVT;
+ break;
+ case F_WRLCKP:
+ fl->fl_owner = (fl_owner_t)filp;
+ fl->fl_type = F_WRLCK;
+ fl->fl_flags |= FL_FILE_PVT;
+ break;
+ case F_UNLCKP:
+ fl->fl_owner = (fl_owner_t)filp;
+ fl->fl_type = F_UNLCK;
+ fl->fl_flags |= FL_FILE_PVT;
+ break;
+ default:
+ /* Any other POSIX lock is owned by the file_struct */
+ fl->fl_owner = current->files;
+ return assign_type(fl, l->l_type);
+ }
+
+ return 0;
}
/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
@@ -2207,6 +2235,8 @@ void locks_remove_file(struct file *filp)
if (!inode->i_flock)
return;
+ locks_remove_posix(filp, (fl_owner_t)filp);
+
if (filp->f_op->flock) {
struct file_lock fl = {
.fl_pid = current->tgid,
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index 36025f7..25eb7be 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -151,6 +151,22 @@ struct f_owner_ex {
#define F_UNLCK 2
#endif
+/*
+ * fd "private" POSIX locks.
+ *
+ * Usually POSIX locks held by a process are released on *any* close and are
+ * not inherited across a fork().
+ *
+ * These lock types will conflict with normal POSIX locks, but are "owned"
+ * by the opened file, not the process. This means that they are inherited
+ * across fork() like BSD (flock) locks, and they are only released
+ * automatically when the last reference to the the open file against which
+ * they were acquired is put.
+ */
+#define F_RDLCKP 5
+#define F_WRLCKP 6
+#define F_UNLCKP 7
+
/* for old implementation of bsd flock () */
#ifndef F_EXLCK
#define F_EXLCK 4 /* or 3 */
--
1.8.4.2
next prev parent reply other threads:[~2013-12-19 13:34 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
2013-12-19 13:34 ` [PATCH v4 01/13] locks: close potential race between setlease and open Jeff Layton
2013-12-19 13:34 ` [PATCH v4 02/13] locks: clean up comment typo Jeff Layton
2013-12-19 13:34 ` [PATCH v4 03/13] locks: remove "inline" qualifier from fl_link manipulation functions Jeff Layton
2013-12-19 13:34 ` [PATCH v4 04/13] locks: add __acquires and __releases annotations to locks_start and locks_stop Jeff Layton
2013-12-19 13:34 ` [PATCH v4 05/13] locks: eliminate BUG() call when there's an unexpected lock on file close Jeff Layton
2013-12-19 13:34 ` [PATCH v4 06/13] locks: consolidate common code in the flock_to_posix_lock routines Jeff Layton
2013-12-19 13:34 ` [PATCH v4 07/13] locks: simplify overflow checking Jeff Layton
2013-12-19 13:34 ` [PATCH v4 08/13] locks: consolidate checks for compatible filp->f_mode values in setlk handlers Jeff Layton
2013-12-19 13:34 ` [PATCH v4 09/13] locks: don't reference original flock struct in F_GETLK handlers Jeff Layton
2013-12-19 13:34 ` [PATCH v4 10/13] locks: rename locks_remove_flock to locks_remove_file Jeff Layton
2013-12-19 13:34 ` [PATCH v4 11/13] locks: show private lock types in /proc/locks Jeff Layton
2013-12-19 13:34 ` [PATCH v4 12/13] locks: report l_pid as -1 for FL_FILE_PVT locks Jeff Layton
2013-12-19 13:34 ` Jeff Layton [this message]
2013-12-19 13:52 ` [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Scott Lovenberg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1387460065-28269-14-git-send-email-jlayton@redhat.com \
--to=jlayton@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nfs-ganesha-devel@lists.sourceforge.net \
--cc=samba-technical@lists.samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).