* [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks
@ 2013-12-19 13:34 Jeff Layton
2013-12-19 13:34 ` [PATCH v4 01/13] locks: close potential race between setlease and open Jeff Layton
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
This patchset is the fourth posting of this set. Behavior between this
set and the last should be more or less the same. Here is a summary of
changes:
v4:
- prefixed the set with the rest of the locks.c patches I have.
- added patch to get rid of BUG() call in locks_remove_flock. I think
a WARN + delete the lock is sufficient there.
- added patches from Bruce to consolidate the struct flock/flock64
to file_lock conversion code
- fixed locks_remove_file not to assume that filp-private locks won't
be added on filesystems that have a ->lock method.
v3:
- more consolidation of common code between flock_to_posix_lock and
flock_to_posix_lock64
- better bisectability by reordering changes, such that partial
implementation won't be exposed
- s/filp/file/ s/FILP/FILE/ in symbol names
v2:
- inheritance semantics have been change to be more BSD-lock like
- patchset size has been reduced by changing how lock ownership
is handled
- new F_UNLCKP l_type value has been added
On the last set, I made note that we could consider implementing this
with new cmd values instead of new l_type values. That's still doable
but I haven't made that change in this set. I'm still open to that
change, but I'd like to hear from others as to which they'd prefer.
Note too that I've gone ahead and opened a request for the POSIX folks
to consider adding this to the POSIX spec once we have something
mergeable. They seem amenable to the idea but don't want to enshrine it
into the standard until there's a real implementation of it:
http://austingroupbugs.net/view.php?id=768
I also owe them a better writeup of the semantics for these new locks,
but have been holding off on doing that until they're a little more
settled.
Original cover letter from v1 posting follows. Comments and suggestions
welcome.
-------------------------------[snip]------------------------------
At LSF this year, there was a discussion about the "wishlist" for
userland file servers. One of the things brought up was the goofy and
problematic behavior of POSIX locks when a file is closed. Boaz started
a thread on it here:
http://permalink.gmane.org/gmane.linux.file-systems/73364
Userland fileservers often need to maintain more than one open file
descriptor on a file. The POSIX spec says:
"All locks associated with a file for a given process shall be removed
when a file descriptor for that file is closed by that process or the
process holding that file descriptor terminates."
This is problematic since you can't close any file descriptor without
dropping all your POSIX locks. Most userland file servers therefore
end up opening the file with more access than is really necessary, and
keeping fd's open for longer than is necessary to work around this.
This patchset is a first stab at an approach to address this problem by
adding two new l_type values -- F_RDLCKP and F_WRLCKP (the 'P' is short
for "private" -- I'm open to changing that if you have a better
mnemonic).
For all intents and purposes these lock types act just like their
"non-P" counterpart. The difference is that they are only implicitly
released when the fd against which they were acquired is closed. As a
side effect, these locks cannot be merged with "non-P" locks since they
have different semantics on close.
I've given this patchset some very basic smoke testing and it seems to
do the right thing, but it is still pretty rough. If this looks
reasonable I'll plan to do some documentation updates and will take a
stab at trying to get these new lock types added to the POSIX spec (as
HCH recommended).
At this point, my main questions are:
1) does this look useful, particularly for fileserver implementors?
2) does this look OK API-wise? We could consider different "cmd" values
or even different syscalls, but I figured this makes it clearer that
"P" and "non-P" locks will still conflict with one another.
J. Bruce Fields (2):
locks: consolidate common code in the flock_to_posix_lock routines
locks: simplify overflow checking
Jeff Layton (11):
locks: close potential race between setlease and open
locks: clean up comment typo
locks: remove "inline" qualifier from fl_link manipulation functions
locks: add __acquires and __releases annotations to locks_start and
locks_stop
locks: eliminate BUG() call when there's an unexpected lock on file
close
locks: consolidate checks for compatible filp->f_mode values in setlk
handlers
locks: don't reference original flock struct in F_GETLK handlers
locks: rename locks_remove_flock to locks_remove_file
locks: show private lock types in /proc/locks
locks: report l_pid as -1 for FL_FILE_PVT locks
locks: add new "private" lock type that is owned by the filp
fs/file_table.c | 2 +-
fs/locks.c | 321 ++++++++++++++++++++++-----------------
include/linux/fs.h | 11 +-
include/uapi/asm-generic/fcntl.h | 19 ++-
4 files changed, 204 insertions(+), 149 deletions(-)
--
1.8.4.2
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 01/13] locks: close potential race between setlease and open
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
@ 2013-12-19 13:34 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 02/13] locks: clean up comment typo Jeff Layton
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
v2:
- fix potential double-free of lease if second check finds conflict
- add smp_mb's to ensure that other CPUs see i_flock changes
v3:
- remove smp_mb calls. Partial ordering is unlikely to help here.
v4:
- add back smp_mb calls. While we have implicit barriers in place
that enforce this today, it's best to be explicit about it as a
defensive coding measure.
As Al Viro points out, there is an unlikely, but possible race between
opening a file and setting a lease on it. generic_add_lease is done with
the i_lock held, but the inode->i_flock check in break_lease is
lockless. It's possible for another task doing an open to do the entire
pathwalk and call break_lease between the point where generic_add_lease
checks for a conflicting open and adds the lease to the list. If this
occurs, we can end up with a lease set on the file with a conflicting
open.
To guard against that, check again for a conflicting open after adding
the lease to the i_flock list. If the above race occurs, then we can
simply unwind the lease setting and return -EAGAIN.
Because we take dentry references and acquire write access on the file
before calling break_lease, we know that if the i_flock list is empty
when the open caller goes to check it then the necessary refcounts have
already been incremented. Thus the additional check for a conflicting
open will see that there is one and the setlease call will fail.
Cc: Bruce Fields <bfields@fieldses.org>
Cc: David Howells <dhowells@redhat.com>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
---
fs/locks.c | 75 ++++++++++++++++++++++++++++++++++++++++++++----------
include/linux/fs.h | 6 +++++
2 files changed, 68 insertions(+), 13 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 92a0f0a..2cfeea6 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -652,15 +652,18 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
locks_insert_global_locks(fl);
}
-/*
- * Delete a lock and then free it.
- * Wake up processes that are blocked waiting for this lock,
- * notify the FS that the lock has been cleared and
- * finally free the lock.
+/**
+ * locks_delete_lock - Delete a lock and then free it.
+ * @thisfl_p: pointer that points to the fl_next field of the previous
+ * inode->i_flock list entry
+ *
+ * Unlink a lock from all lists and free the namespace reference, but don't
+ * free it yet. Wake up processes that are blocked waiting for this lock and
+ * notify the FS that the lock has been cleared.
*
* Must be called with the i_lock held!
*/
-static void locks_delete_lock(struct file_lock **thisfl_p)
+static void locks_unlink_lock(struct file_lock **thisfl_p)
{
struct file_lock *fl = *thisfl_p;
@@ -675,6 +678,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
}
locks_wake_up_blocks(fl);
+}
+
+/*
+ * Unlink a lock from all lists and free it.
+ *
+ * Must be called with i_lock held!
+ */
+static void locks_delete_lock(struct file_lock **thisfl_p)
+{
+ struct file_lock *fl = *thisfl_p;
+
+ locks_unlink_lock(thisfl_p);
locks_free_lock(fl);
}
@@ -1472,6 +1487,32 @@ int fcntl_getlease(struct file *filp)
return type;
}
+/**
+ * check_conflicting_open - see if the given dentry points to a file that has
+ * an existing open that would conflict with the
+ * desired lease.
+ * @dentry: dentry to check
+ * @arg: type of lease that we're trying to acquire
+ *
+ * Check to see if there's an existing open fd on this file that would
+ * conflict with the lease we're trying to set.
+ */
+static int
+check_conflicting_open(const struct dentry *dentry, const long arg)
+{
+ int ret = 0;
+ struct inode *inode = dentry->d_inode;
+
+ if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+ return -EAGAIN;
+
+ if ((arg == F_WRLCK) && ((d_count(dentry) > 1) ||
+ (atomic_read(&inode->i_count) > 1)))
+ ret = -EAGAIN;
+
+ return ret;
+}
+
static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp)
{
struct file_lock *fl, **before, **my_before = NULL, *lease;
@@ -1499,12 +1540,8 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
return -EINVAL;
}
- error = -EAGAIN;
- if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
- goto out;
- if ((arg == F_WRLCK)
- && ((d_count(dentry) > 1)
- || (atomic_read(&inode->i_count) > 1)))
+ error = check_conflicting_open(dentry, arg);
+ if (error)
goto out;
/*
@@ -1549,7 +1586,19 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
goto out;
locks_insert_lock(before, lease);
- error = 0;
+ /*
+ * The check in break_lease() is lockless. It's possible for another
+ * open to race in after we did the earlier check for a conflicting
+ * open but before the lease was inserted. Check again for a
+ * conflicting open and cancel the lease if there is one.
+ *
+ * We also add a barrier here to ensure that the insertion of the lock
+ * precedes these checks.
+ */
+ smp_mb();
+ error = check_conflicting_open(dentry, arg);
+ if (error)
+ locks_unlink_lock(flp);
out:
if (is_deleg)
mutex_unlock(&inode->i_mutex);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 121f11f..04be202 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1963,6 +1963,12 @@ static inline int locks_verify_truncate(struct inode *inode,
static inline int break_lease(struct inode *inode, unsigned int mode)
{
+ /*
+ * Since this check is lockless, we must ensure that any refcounts
+ * taken are done before checking inode->i_flock. Otherwise, we could
+ * end up racing with tasks trying to set a new lease on this file.
+ */
+ smp_mb();
if (inode->i_flock)
return __break_lease(inode, mode, FL_LEASE);
return 0;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 02/13] locks: clean up comment typo
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 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 03/13] locks: remove "inline" qualifier from fl_link manipulation functions Jeff Layton
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/locks.c b/fs/locks.c
index 2cfeea6..5e28612 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -581,7 +581,7 @@ static void locks_delete_block(struct file_lock *waiter)
* it seems like the reasonable thing to do.
*
* Must be called with both the i_lock and blocked_lock_lock held. The fl_block
- * list itself is protected by the file_lock_list, but by ensuring that the
+ * list itself is protected by the blocked_lock_lock, but by ensuring that the
* i_lock is also held on insertions we can avoid taking the blocked_lock_lock
* in some cases when we see that the fl_block list is empty.
*/
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 03/13] locks: remove "inline" qualifier from fl_link manipulation functions
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 ` 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
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
It's best to let the compiler decide that.
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 5e28612..049a144 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -511,8 +511,7 @@ static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
}
/* Must be called with the i_lock held! */
-static inline void
-locks_insert_global_locks(struct file_lock *fl)
+static void locks_insert_global_locks(struct file_lock *fl)
{
lg_local_lock(&file_lock_lglock);
fl->fl_link_cpu = smp_processor_id();
@@ -521,8 +520,7 @@ locks_insert_global_locks(struct file_lock *fl)
}
/* Must be called with the i_lock held! */
-static inline void
-locks_delete_global_locks(struct file_lock *fl)
+static void locks_delete_global_locks(struct file_lock *fl)
{
/*
* Avoid taking lock if already unhashed. This is safe since this check
@@ -544,14 +542,12 @@ posix_owner_key(struct file_lock *fl)
return (unsigned long)fl->fl_owner;
}
-static inline void
-locks_insert_global_blocked(struct file_lock *waiter)
+static void locks_insert_global_blocked(struct file_lock *waiter)
{
hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter));
}
-static inline void
-locks_delete_global_blocked(struct file_lock *waiter)
+static void locks_delete_global_blocked(struct file_lock *waiter)
{
hash_del(&waiter->fl_link);
}
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 04/13] locks: add __acquires and __releases annotations to locks_start and locks_stop
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (2 preceding siblings ...)
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 ` 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
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
...to make sparse happy.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/locks.c b/fs/locks.c
index 049a144..6084f5a 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2430,6 +2430,7 @@ static int locks_show(struct seq_file *f, void *v)
}
static void *locks_start(struct seq_file *f, loff_t *pos)
+ __acquires(&blocked_lock_lock)
{
struct locks_iterator *iter = f->private;
@@ -2448,6 +2449,7 @@ static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
}
static void locks_stop(struct seq_file *f, void *v)
+ __releases(&blocked_lock_lock)
{
spin_unlock(&blocked_lock_lock);
lg_global_unlock(&file_lock_lglock);
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 05/13] locks: eliminate BUG() call when there's an unexpected lock on file close
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (3 preceding siblings ...)
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 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 06/13] locks: consolidate common code in the flock_to_posix_lock routines Jeff Layton
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
A leftover lock on the list is surely a sign of a problem of some sort,
but it's not necessarily a reason to panic the box. Instead, just log a
warning with some info about the lock, and then delete it like we would
any other lock.
In the event that the filesystem declares a ->lock f_op, we may end up
leaking something, but that's generally preferable to an immediate
panic.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 6084f5a..dd30933 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2281,16 +2281,28 @@ void locks_remove_flock(struct file *filp)
while ((fl = *before) != NULL) {
if (fl->fl_file == filp) {
- if (IS_FLOCK(fl)) {
- locks_delete_lock(before);
- continue;
- }
if (IS_LEASE(fl)) {
lease_modify(before, F_UNLCK);
continue;
}
- /* What? */
- BUG();
+
+ /*
+ * There's a leftover lock on the list of a type that
+ * we didn't expect to see. Most likely a classic
+ * POSIX lock that ended up not getting released
+ * properly, or that raced onto the list somehow. Log
+ * some info about it and then just remove it from
+ * the list.
+ */
+ WARN(!IS_FLOCK(fl),
+ "leftover lock: dev=%u:%u ino=%lu type=%hhd flags=0x%x start=%lld end=%lld\n",
+ MAJOR(inode->i_sb->s_dev),
+ MINOR(inode->i_sb->s_dev), inode->i_ino,
+ fl->fl_type, fl->fl_flags,
+ fl->fl_start, fl->fl_end);
+
+ locks_delete_lock(before);
+ continue;
}
before = &fl->fl_next;
}
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 06/13] locks: consolidate common code in the flock_to_posix_lock routines
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (4 preceding siblings ...)
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 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 07/13] locks: simplify overflow checking Jeff Layton
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
From: "J. Bruce Fields" <bfields@fieldses.org>
Currently, there's a lot of copy and paste between the two. Add some
functions to do the initialization of the file_lock from values
passed in, and turn the flock/flock64 variants of those functions into
wrappers around them.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@fieldses.org>
---
fs/locks.c | 112 +++++++++++++++------------------------
include/uapi/asm-generic/fcntl.h | 3 --
2 files changed, 44 insertions(+), 71 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index dd30933..863f4df 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -344,48 +344,42 @@ static int assign_type(struct file_lock *fl, long type)
return 0;
}
-/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
- * style lock.
- */
-static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
- struct flock *l)
+static int flock_to_posix_lock_common(struct file *filp, struct file_lock *fl,
+ struct flock64 *l, loff_t offset_max)
{
- off_t start, end;
-
switch (l->l_whence) {
case SEEK_SET:
- start = 0;
+ fl->fl_start = 0;
break;
case SEEK_CUR:
- start = filp->f_pos;
+ fl->fl_start = filp->f_pos;
break;
case SEEK_END:
- start = i_size_read(file_inode(filp));
+ fl->fl_start = i_size_read(file_inode(filp));
break;
default:
return -EINVAL;
}
+ if (l->l_start > offset_max - fl->fl_start)
+ return -EOVERFLOW;
+ fl->fl_start += l->l_start;
+ if (fl->fl_start < 0)
+ return -EINVAL;
+ if (l->l_len > offset_max - fl->fl_start)
+ return -EOVERFLOW;
+ if (fl->fl_start + l->l_len < 0)
+ return -EINVAL;
/* POSIX-1996 leaves the case l->l_len < 0 undefined;
POSIX-2001 defines it. */
- start += l->l_start;
- if (start < 0)
- return -EINVAL;
- fl->fl_end = OFFSET_MAX;
- if (l->l_len > 0) {
- end = start + l->l_len - 1;
- fl->fl_end = end;
- } else if (l->l_len < 0) {
- end = start - 1;
- fl->fl_end = end;
- start += l->l_len;
- if (start < 0)
- return -EINVAL;
- }
- fl->fl_start = start; /* we record the absolute position */
- if (fl->fl_end < fl->fl_start)
- return -EOVERFLOW;
-
+ if (l->l_len > 0)
+ fl->fl_end = fl->fl_start + l->l_len - 1;
+ else if (l->l_len < 0) {
+ fl->fl_end = fl->fl_start - 1;
+ fl->fl_start += l->l_len;
+ } else
+ fl->fl_end = OFFSET_MAX;
+
fl->fl_owner = current->files;
fl->fl_pid = current->tgid;
fl->fl_file = filp;
@@ -396,50 +390,32 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
return assign_type(fl, l->l_type);
}
+/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
+ * style lock.
+ */
+static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
+ struct flock *l)
+{
+ struct flock64 ll = {
+ .l_type = l->l_type,
+ .l_whence = l->l_whence,
+ .l_start = l->l_start,
+ .l_len = l->l_len,
+ };
+
+ /*
+ * The use of OFFT_OFFSET_MAX here ensures we return -EOVERFLOW
+ * if the start or end of the lock could not be represented as
+ * an off_t, following SUSv3.
+ */
+ return flock_to_posix_lock_common(filp, fl, &ll, OFFT_OFFSET_MAX);
+}
+
#if BITS_PER_LONG == 32
static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
struct flock64 *l)
{
- loff_t start;
-
- switch (l->l_whence) {
- case SEEK_SET:
- start = 0;
- break;
- case SEEK_CUR:
- start = filp->f_pos;
- break;
- case SEEK_END:
- start = i_size_read(file_inode(filp));
- break;
- default:
- return -EINVAL;
- }
-
- start += l->l_start;
- if (start < 0)
- return -EINVAL;
- fl->fl_end = OFFSET_MAX;
- if (l->l_len > 0) {
- fl->fl_end = start + l->l_len - 1;
- } else if (l->l_len < 0) {
- fl->fl_end = start - 1;
- start += l->l_len;
- if (start < 0)
- return -EINVAL;
- }
- fl->fl_start = start; /* we record the absolute position */
- if (fl->fl_end < fl->fl_start)
- return -EOVERFLOW;
-
- fl->fl_owner = current->files;
- fl->fl_pid = current->tgid;
- fl->fl_file = filp;
- fl->fl_flags = FL_POSIX;
- fl->fl_ops = NULL;
- fl->fl_lmops = NULL;
-
- return assign_type(fl, l->l_type);
+ return flock_to_posix_lock_common(filp, fl, l, OFFSET_MAX);
}
#endif
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index 95e46c8..36025f7 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -186,8 +186,6 @@ struct flock {
};
#endif
-#ifndef CONFIG_64BIT
-
#ifndef HAVE_ARCH_STRUCT_FLOCK64
#ifndef __ARCH_FLOCK64_PAD
#define __ARCH_FLOCK64_PAD
@@ -202,6 +200,5 @@ struct flock64 {
__ARCH_FLOCK64_PAD
};
#endif
-#endif /* !CONFIG_64BIT */
#endif /* _ASM_GENERIC_FCNTL_H */
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 07/13] locks: simplify overflow checking
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (5 preceding siblings ...)
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 ` 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
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
From: "J. Bruce Fields" <bfields@fieldses.org>
Or maybe we don't actually care about indicating overflow in the 32-bit
case: sure we could fail if e.g. f_pos+start or f_pos+start+len would
exceed 32-bits, but do we really need to?
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
---
fs/locks.c | 23 +++++------------------
1 file changed, 5 insertions(+), 18 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 863f4df..1555b05 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -344,8 +344,8 @@ static int assign_type(struct file_lock *fl, long type)
return 0;
}
-static int flock_to_posix_lock_common(struct file *filp, struct file_lock *fl,
- struct flock64 *l, loff_t offset_max)
+static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
+ struct flock64 *l)
{
switch (l->l_whence) {
case SEEK_SET:
@@ -360,12 +360,12 @@ static int flock_to_posix_lock_common(struct file *filp, struct file_lock *fl,
default:
return -EINVAL;
}
- if (l->l_start > offset_max - fl->fl_start)
+ if (l->l_start > OFFSET_MAX - fl->fl_start)
return -EOVERFLOW;
fl->fl_start += l->l_start;
if (fl->fl_start < 0)
return -EINVAL;
- if (l->l_len > offset_max - fl->fl_start)
+ if (l->l_len > OFFSET_MAX - fl->fl_start)
return -EOVERFLOW;
if (fl->fl_start + l->l_len < 0)
return -EINVAL;
@@ -403,22 +403,9 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
.l_len = l->l_len,
};
- /*
- * The use of OFFT_OFFSET_MAX here ensures we return -EOVERFLOW
- * if the start or end of the lock could not be represented as
- * an off_t, following SUSv3.
- */
- return flock_to_posix_lock_common(filp, fl, &ll, OFFT_OFFSET_MAX);
+ return flock64_to_posix_lock(filp, fl, &ll);
}
-#if BITS_PER_LONG == 32
-static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
- struct flock64 *l)
-{
- return flock_to_posix_lock_common(filp, fl, l, OFFSET_MAX);
-}
-#endif
-
/* default lease lock manager operations */
static void lease_break_callback(struct file_lock *fl)
{
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 08/13] locks: consolidate checks for compatible filp->f_mode values in setlk handlers
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (6 preceding siblings ...)
2013-12-19 13:34 ` [PATCH v4 07/13] locks: simplify overflow checking Jeff Layton
@ 2013-12-19 13:34 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 09/13] locks: don't reference original flock struct in F_GETLK handlers Jeff Layton
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
Move this check into flock64_to_posix_lock instead of duplicating it in
two places. This also fixes a minor wart in the code where we continue
referring to the struct flock after converting it to struct file_lock.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 46 ++++++++++++----------------------------------
1 file changed, 12 insertions(+), 34 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 1555b05..820322d 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -387,6 +387,18 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
fl->fl_ops = NULL;
fl->fl_lmops = NULL;
+ /* Ensure that fl->fl_filp has compatible f_mode */
+ switch (l->l_type) {
+ case F_RDLCK:
+ if (!(filp->f_mode & FMODE_READ))
+ return -EBADF;
+ break;
+ case F_WRLCK:
+ if (!(filp->f_mode & FMODE_WRITE))
+ return -EBADF;
+ break;
+ }
+
return assign_type(fl, l->l_type);
}
@@ -2024,23 +2036,6 @@ again:
file_lock->fl_flags |= FL_SLEEP;
}
- error = -EBADF;
- switch (flock.l_type) {
- case F_RDLCK:
- if (!(filp->f_mode & FMODE_READ))
- goto out;
- break;
- case F_WRLCK:
- if (!(filp->f_mode & FMODE_WRITE))
- goto out;
- break;
- case F_UNLCK:
- break;
- default:
- error = -EINVAL;
- goto out;
- }
-
error = do_lock_file_wait(filp, cmd, file_lock);
/*
@@ -2142,23 +2137,6 @@ again:
file_lock->fl_flags |= FL_SLEEP;
}
- error = -EBADF;
- switch (flock.l_type) {
- case F_RDLCK:
- if (!(filp->f_mode & FMODE_READ))
- goto out;
- break;
- case F_WRLCK:
- if (!(filp->f_mode & FMODE_WRITE))
- goto out;
- break;
- case F_UNLCK:
- break;
- default:
- error = -EINVAL;
- goto out;
- }
-
error = do_lock_file_wait(filp, cmd, file_lock);
/*
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 09/13] locks: don't reference original flock struct in F_GETLK handlers
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (7 preceding siblings ...)
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 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 10/13] locks: rename locks_remove_flock to locks_remove_file Jeff Layton
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
The locks code currently sanity checks the type values in the flock
struct before doing the flock->file_lock conversion. That will be
problematic when new l_type values are introduced in a later patch.
Instead, do the flock_to_posix_lock conversion first, and then sanity
check the values in the file_lock instead.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 820322d..8180141 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1905,14 +1905,15 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
error = -EFAULT;
if (copy_from_user(&flock, l, sizeof(flock)))
goto out;
- error = -EINVAL;
- if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
- goto out;
error = flock_to_posix_lock(filp, &file_lock, &flock);
if (error)
goto out;
+ error = -EINVAL;
+ if ((file_lock.fl_type != F_RDLCK) && (file_lock.fl_type != F_WRLCK))
+ goto out;
+
error = vfs_test_lock(filp, &file_lock);
if (error)
goto out;
@@ -2073,14 +2074,15 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
error = -EFAULT;
if (copy_from_user(&flock, l, sizeof(flock)))
goto out;
- error = -EINVAL;
- if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
- goto out;
error = flock64_to_posix_lock(filp, &file_lock, &flock);
if (error)
goto out;
+ error = -EINVAL;
+ if ((file_lock.fl_type != F_RDLCK) && (file_lock.fl_type != F_WRLCK))
+ goto out;
+
error = vfs_test_lock(filp, &file_lock);
if (error)
goto out;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 10/13] locks: rename locks_remove_flock to locks_remove_file
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (8 preceding siblings ...)
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 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 11/13] locks: show private lock types in /proc/locks Jeff Layton
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
This function currently removes leases in addition to flock locks and in
a later patch we'll have it deal with a new type of POSIX lock too.
Rename it to locks_remove_file to indicate that it removes locks that
are associated with a particular struct file, and not just flock locks.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/file_table.c | 2 +-
fs/locks.c | 2 +-
include/linux/fs.h | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/file_table.c b/fs/file_table.c
index 5fff903..468543c 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -234,7 +234,7 @@ static void __fput(struct file *file)
* in the file cleanup chain.
*/
eventpoll_release(file);
- locks_remove_flock(file);
+ locks_remove_file(file);
if (unlikely(file->f_flags & FASYNC)) {
if (file->f_op->fasync)
diff --git a/fs/locks.c b/fs/locks.c
index 8180141..a217c2c 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2197,7 +2197,7 @@ EXPORT_SYMBOL(locks_remove_posix);
/*
* This function is called on the last close of an open file.
*/
-void locks_remove_flock(struct file *filp)
+void locks_remove_file(struct file *filp)
{
struct inode * inode = file_inode(filp);
struct file_lock *fl;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 04be202..51974e0 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1012,7 +1012,7 @@ extern struct file_lock * locks_alloc_lock(void);
extern void locks_copy_lock(struct file_lock *, struct file_lock *);
extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
extern void locks_remove_posix(struct file *, fl_owner_t);
-extern void locks_remove_flock(struct file *);
+extern void locks_remove_file(struct file *);
extern void locks_release_private(struct file_lock *);
extern void posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
@@ -1083,7 +1083,7 @@ static inline void locks_remove_posix(struct file *filp, fl_owner_t owner)
return;
}
-static inline void locks_remove_flock(struct file *filp)
+static inline void locks_remove_file(struct file *filp)
{
return;
}
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 11/13] locks: show private lock types in /proc/locks
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (9 preceding siblings ...)
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 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 12/13] locks: report l_pid as -1 for FL_FILE_PVT locks Jeff Layton
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
In a later patch, we'll be adding a new type of lock that's owned by
the struct file instead of the files_struct. Those sorts of locks
will be flagged with a new IS_FILE_PVT flag.
Show "private" locks in /proc/locks with a 'P' suffix. This does mean
that we need to widen the column by one character.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 9 ++++++---
include/linux/fs.h | 1 +
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index a217c2c..995583b 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -135,6 +135,7 @@
#define IS_POSIX(fl) (fl->fl_flags & FL_POSIX)
#define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK)
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG))
+#define IS_FILE_PVT(fl) (fl->fl_flags & FL_FILE_PVT)
static bool lease_breaking(struct file_lock *fl)
{
@@ -2336,13 +2337,15 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
seq_printf(f, "UNKNOWN UNKNOWN ");
}
if (fl->fl_type & LOCK_MAND) {
- seq_printf(f, "%s ",
+ seq_printf(f, "%s ",
(fl->fl_type & LOCK_READ)
? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ "
: (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE ");
+ } else if (IS_FILE_PVT(fl)) {
+ seq_printf(f, "%s ", fl->fl_type == F_WRLCK ? "WRITEP" : "READP ");
} else {
- seq_printf(f, "%s ",
- (lease_breaking(fl))
+ seq_printf(f, "%s ",
+ lease_breaking(fl)
? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ "
: (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 51974e0..639a3b7 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -888,6 +888,7 @@ static inline int file_check_writeable(struct file *filp)
#define FL_SLEEP 128 /* A blocking lock */
#define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */
#define FL_UNLOCK_PENDING 512 /* Lease is being broken */
+#define FL_FILE_PVT 1024 /* lock is private to the file */
/*
* Special return value from posix_lock_file() and vfs_lock_file() for
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 12/13] locks: report l_pid as -1 for FL_FILE_PVT locks
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (10 preceding siblings ...)
2013-12-19 13:34 ` [PATCH v4 11/13] locks: show private lock types in /proc/locks Jeff Layton
@ 2013-12-19 13:34 ` Jeff Layton
2013-12-19 13:34 ` [PATCH v4 13/13] locks: add new "private" lock type that is owned by the filp Jeff Layton
2013-12-19 13:52 ` [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Scott Lovenberg
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
FL_FILE_PVT locks are no longer tied to a particular pid, and are
instead inheritable by child processes. Report a l_pid of '-1' for
these sorts of locks since the pid is somewhat meaningless for them.
This precedent comes from FreeBSD. There, POSIX and flock() locks can
conflict with one another. If fcntl(F_GETLK, ...) returns a lock set
with flock() then the l_pid member cannot be a process ID because the
lock is not held by a process as such.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/locks.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 995583b..013b177 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1863,7 +1863,7 @@ EXPORT_SYMBOL_GPL(vfs_test_lock);
static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
{
- flock->l_pid = fl->fl_pid;
+ flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
#if BITS_PER_LONG == 32
/*
* Make sure we can represent the posix lock via
@@ -1885,7 +1885,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
#if BITS_PER_LONG == 32
static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
{
- flock->l_pid = fl->fl_pid;
+ flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
flock->l_start = fl->fl_start;
flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
fl->fl_end - fl->fl_start + 1;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 13/13] locks: add new "private" lock type that is owned by the filp
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (11 preceding siblings ...)
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
2013-12-19 13:52 ` [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Scott Lovenberg
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Layton @ 2013-12-19 13:34 UTC (permalink / raw)
To: linux-fsdevel; +Cc: nfs-ganesha-devel, samba-technical, linux-kernel
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
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks
2013-12-19 13:34 [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Jeff Layton
` (12 preceding siblings ...)
2013-12-19 13:34 ` [PATCH v4 13/13] locks: add new "private" lock type that is owned by the filp Jeff Layton
@ 2013-12-19 13:52 ` Scott Lovenberg
13 siblings, 0 replies; 15+ messages in thread
From: Scott Lovenberg @ 2013-12-19 13:52 UTC (permalink / raw)
To: Jeff Layton; +Cc: linux-fsdevel, Ganesha NFS List, samba-technical, LKML
On Thu, Dec 19, 2013 at 8:34 AM, Jeff Layton <jlayton@redhat.com> wrote:
>
> This patchset is the fourth posting of this set. Behavior between this
> set and the last should be more or less the same. Here is a summary of
> changes:
>
>
Go, Jeff, go! Seriously, it's awesome you're bringing the UNPOSIX
locking code forward.
--
Peace and Blessings,
-Scott.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2013-12-19 13:52 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH v4 13/13] locks: add new "private" lock type that is owned by the filp Jeff Layton
2013-12-19 13:52 ` [PATCH v4 00/13] locks: implement "filp-private" (aka UNPOSIX) locks Scott Lovenberg
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).