locks: Ability to test for flock presence on fd
Subsystems (4)
PATCH 1/1 locks: Ability to test for flock presence on fd
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in /proc/locks is the pid of the task who created the flock, not the one who _may_ hold it.
If the flock creator shared the file with some other task (by forking or via scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.
This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a LOCK_SH lock on the file and then "obfuscated" the owner field in /proc/locks. After this we have no ways to find out who is the lock holder.
I'd like to note, that for LOCK_EX this problem is not critical -- we may go to both tasks and "ask" them to LOCK_EX the file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder. With LOCK_SH this doesn't work. Trying to drop the lock doesn't work either, as flock(LOCK_UN) reports 0 in both cases:
if the file is locked and if it is not.
That said, I'd like to propose the LOCK_TEST flag to the flock call, that would check whether the lock of the given type (LOCK_SH or LOCK_EX) exists on the file we test. It's not the same as the existing in-kernel FL_ACCESS flag, which checks whether the new lock is possible, but it's a new FL_TEST flag, that checks whether the existing lock is there.
What do you think?
---
fs/locks.c +13 -3
@@ -830,7 +830,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)int found =0 ;LIST_HEAD (dispose); -if (!(request->fl_flags &FL_ACCESS ) && (request->fl_type !=F_UNLCK )) { +if (!(request->fl_flags & (FL_ACCESS |FL_TEST )) && (request->fl_type !=F_UNLCK )) { new_fl =locks_alloc_lock ();if (!new_fl)return -ENOMEM ;
@@ -850,11 +850,18 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)continue ;if (request->fl_type == fl->fl_type) goto out; +if (request->fl_flags &FL_TEST ) +break ; found =1 ;locks_delete_lock (before, &dispose);break ; } +if (request->fl_flags &FL_TEST ) { + error = -ENOENT ; + goto out; + } +if (request->fl_type ==F_UNLCK ) {if ((request->fl_flags &FL_EXISTS ) && !found) error = -ENOENT ;
@@ -1852,15 +1859,16 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) {struct fd f =fdget (fd);struct file_lock *lock; -int can_sleep, unlock; +int can_sleep, unlock, test;int error; error = -EBADF ;if (!f.file) goto out; + test = (cmd &LOCK_TEST ); can_sleep = !(cmd &LOCK_NB ); - cmd &= ~LOCK_NB ; + cmd &= ~(LOCK_NB |LOCK_TEST ); unlock = (cmd ==LOCK_UN ); if (!unlock && !(cmd & LOCK_MAND) &&
@@ -1872,6 +1880,8 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) goto out_putf;if (can_sleep) lock->fl_flags |=FL_SLEEP ; +if (test) + lock->fl_flags |=FL_TEST ; error =security_file_lock (f.file, lock->fl_type);if (error)
include/linux/fs.h +1 -0
@@ -844,6 +844,7 @@ static inline struct file *get_file(struct file *f)#define FL_DOWNGRADE_PENDING 256/* Lease is being downgraded */ #define FL_UNLOCK_PENDING 512/* Lease is being broken */ #define FL_OFDLCK 1024/* lock is "owned" by struct file */ +#define FL_TEST 2048/* * Special return value from posix_lock_file() and vfs_lock_file() for
include/uapi/asm-generic/fcntl.h +1 -0
@@ -184,6 +184,7 @@ struct f_owner_ex {#define LOCK_READ 64/* which allows concurrent read operations */ #define LOCK_WRITE 128/* which allows concurrent write operations */ #define LOCK_RW 192/* which allows concurrent read & write ops */ +#define LOCK_TEST 256/* check for my SH|EX locks present */ #define F_LINUX_SPECIFIC_BASE 1024
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.
It could be both, actually, right?
Quoted 11 lines
With
LOCK_SHthis doesn't work. Trying to drop the
lock doesn't work either, asflock(LOCK_UN)reports 0 in both cases:
if the file is locked and if it is not.That said, I'd like to propose the
LOCK_TESTflag to the flock call, that would check whether the lock of the given type (LOCK_SHorLOCK_EX) exists on the file we test. It's not the same as the existing in-kernelFL_ACCESSflag, which checks whether the new lock is possible, but it's a newFL_TESTflag, that checks whether the existing lock is there.What do you think?
I guess I can't see anything really wrong with it.
It ignores the (poorly documented) LOCK_MAND case, but maybe that's OK.
Would it make sense to return the lock type held instead, so you could do one flock(fd, LOCK_TEST) instead of flock(fd, LOCK_TEST|LOCK_SH) and flock(fd, LOCK_TEST|LOCK_EX) ?
It'd be nice if we could fix /proc/locks. (You'd think I'd know better, but I've certainly been confused before when /proc/locks told me a lock was owned by a nonexistant PID.) But as long as multiple PIDs can "own" a flock and as long as there's no simple ID we can use to refer to a given struct file, I don't see an easy solution.
--b.
Quoted 90 lines
Signed-off-by Pavel Emelyanov <[email protected]>---
fs/locks.c +13
-3@@ -830,7 +830,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)int found =0 ;LIST_HEAD (dispose); -if (!(request->fl_flags &FL_ACCESS ) && (request->fl_type !=F_UNLCK )) { +if (!(request->fl_flags & (FL_ACCESS |FL_TEST )) && (request->fl_type !=F_UNLCK )) { new_fl =locks_alloc_lock ();if (!new_fl)return -ENOMEM ;@@ -850,11 +850,18 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)continue ;if (request->fl_type == fl->fl_type) goto out; +if (request->fl_flags &FL_TEST ) +break ; found =1 ;locks_delete_lock (before, &dispose);break ; } +if (request->fl_flags &FL_TEST ) { + error = -ENOENT ; + goto out; + } +if (request->fl_type ==F_UNLCK ) {if ((request->fl_flags &FL_EXISTS ) && !found) error = -ENOENT ;@@ -1852,15 +1859,16 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) {struct fd f =fdget (fd);struct file_lock *lock; -int can_sleep, unlock; +int can_sleep, unlock, test;int error; error = -EBADF ;if (!f.file) goto out; + test = (cmd &LOCK_TEST ); can_sleep = !(cmd &LOCK_NB ); - cmd &= ~LOCK_NB ; + cmd &= ~(LOCK_NB |LOCK_TEST ); unlock = (cmd ==LOCK_UN ); if (!unlock && !(cmd & LOCK_MAND) &&@@ -1872,6 +1880,8 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) goto out_putf;if (can_sleep) lock->fl_flags |=FL_SLEEP ; +if (test) + lock->fl_flags |=FL_TEST ; error =security_file_lock (f.file, lock->fl_type);if (error)include/linux/fs.h +1
-0@@ -844,6 +844,7 @@ static inline struct file *get_file(struct file *f)#define FL_DOWNGRADE_PENDING 256/* Lease is being downgraded */ #define FL_UNLOCK_PENDING 512/* Lease is being broken */ #define FL_OFDLCK 1024/* lock is "owned" by struct file */ +#define FL_TEST 2048/* * Special return value from posix_lock_file() and vfs_lock_file() for include/uapi/asm-generic/fcntl.h +1
-0@@ -184,6 +184,7 @@ struct f_owner_ex {#define LOCK_READ 64/* which allows concurrent read operations */ #define LOCK_WRITE 128/* which allows concurrent write operations */ #define LOCK_RW 192/* which allows concurrent read & write ops */ +#define LOCK_TEST 256/* check for my SH|EX locks present */ #define F_LINUX_SPECIFIC_BASE 1024
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with LOCK_EX? AFAIU no. Am I missing something?
Quoted 10 lines
Quoted 10 lines
With
LOCK_SHthis doesn't work. Trying to drop the
lock doesn't work either, asflock(LOCK_UN)reports 0 in both cases:
if the file is locked and if it is not.That said, I'd like to propose the
LOCK_TESTflag to the flock call, that would check whether the lock of the given type (LOCK_SHorLOCK_EX) exists on the file we test. It's not the same as the existing in-kernelFL_ACCESSflag, which checks whether the new lock is possible, but it's a newFL_TESTflag, that checks whether the existing lock is there.
Quoted 5 lines
Quoted 1 line
What do you think?
I guess I can't see anything really wrong with it.
It ignores the (poorly documented)
LOCK_MANDcase, but maybe that's OK.
I actually checked it and it seemed to work. What problems do you see with this case?
Quoted 3 lines
Would it make sense to return the lock type held instead, so you could do one
flock(fd, LOCK_TEST)instead offlock(fd, LOCK_TEST|LOCK_SH)andflock(fd, LOCK_TEST|LOCK_EX)?
Well, in our case we parse /proc/locks anyway to see what files at least to test for being locked. But what you propose looks even better. I'll look what can be done here.
Quoted 101 lines
It'd be nice if we could fix
/proc/locks. (You'd think I'd know better, but I've certainly been confused before when/proc/lockstold me a lock was owned by a nonexistant PID.) But as long as multiple PIDs can "own" a flock and as long as there's no simple ID we can use to refer to a given struct file, I don't see an easy solution.--b.
Quoted 83 lines
Signed-off-by Pavel Emelyanov <[email protected]>---
fs/locks.c +13
-3@@ -830,7 +830,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)int found =0 ;LIST_HEAD (dispose); -if (!(request->fl_flags &FL_ACCESS ) && (request->fl_type !=F_UNLCK )) { +if (!(request->fl_flags & (FL_ACCESS |FL_TEST )) && (request->fl_type !=F_UNLCK )) { new_fl =locks_alloc_lock ();if (!new_fl)return -ENOMEM ;@@ -850,11 +850,18 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)continue ;if (request->fl_type == fl->fl_type) goto out; +if (request->fl_flags &FL_TEST ) +break ; found =1 ;locks_delete_lock (before, &dispose);break ; } +if (request->fl_flags &FL_TEST ) { + error = -ENOENT ; + goto out; + } +if (request->fl_type ==F_UNLCK ) {if ((request->fl_flags &FL_EXISTS ) && !found) error = -ENOENT ;@@ -1852,15 +1859,16 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) {struct fd f =fdget (fd);struct file_lock *lock; -int can_sleep, unlock; +int can_sleep, unlock, test;int error; error = -EBADF ;if (!f.file) goto out; + test = (cmd &LOCK_TEST ); can_sleep = !(cmd &LOCK_NB ); - cmd &= ~LOCK_NB ; + cmd &= ~(LOCK_NB |LOCK_TEST ); unlock = (cmd ==LOCK_UN ); if (!unlock && !(cmd & LOCK_MAND) &&@@ -1872,6 +1880,8 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) goto out_putf;if (can_sleep) lock->fl_flags |=FL_SLEEP ; +if (test) + lock->fl_flags |=FL_TEST ; error =security_file_lock (f.file, lock->fl_type);if (error)include/linux/fs.h +1
-0@@ -844,6 +844,7 @@ static inline struct file *get_file(struct file *f)#define FL_DOWNGRADE_PENDING 256/* Lease is being downgraded */ #define FL_UNLOCK_PENDING 512/* Lease is being broken */ #define FL_OFDLCK 1024/* lock is "owned" by struct file */ +#define FL_TEST 2048/* * Special return value from posix_lock_file() and vfs_lock_file() for include/uapi/asm-generic/fcntl.h +0
-0include/uapi/asm-generic/fcntl.h struct f_owner_ex { · line 190
Quoted 7 lines
include/uapi/asm-generic/fcntl.h +1
-0@@ -184,6 +184,7 @@ struct f_owner_ex {#define LOCK_READ 64/* which allows concurrent read operations */ #define LOCK_WRITE 128/* which allows concurrent write operations */ #define LOCK_RW 192/* which allows concurrent read & write ops */ +#define LOCK_TEST 256/* check for my SH|EX locks present */ #define F_LINUX_SPECIFIC_BASE 1024.
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?
After a fork, two processes "own" the lock, right?:
int main(int argc, char *argv[])
{
int fd, ret;
fd = open(argv[1], O_RDWR);
ret = flock(fd, LOCK_EX);
if (ret)
err(1, "flock");
ret = fork();
if (ret == -1)
err(1, "flock");
ret = flock(fd, LOCK_EX);
if (ret)
err(1, "flock");
printf("%d got exclusive lock\n", getpid());
sleep(1000);
}
$ touch TMP
$ ./test TMP
15882 got exclusive lock
15883 got exclusive lock
^CI may misunderstand what you're doing.
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
With
LOCK_SHthis doesn't work. Trying to drop the
lock doesn't work either, asflock(LOCK_UN)reports 0 in both cases:
if the file is locked and if it is not.That said, I'd like to propose the
LOCK_TESTflag to the flock call, that would check whether the lock of the given type (LOCK_SHorLOCK_EX) exists on the file we test. It's not the same as the existing in-kernelFL_ACCESSflag, which checks whether the new lock is possible, but it's a newFL_TESTflag, that checks whether the existing lock is there.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
What do you think?
I guess I can't see anything really wrong with it.
It ignores the (poorly documented)
LOCK_MANDcase, but maybe that's OK.I actually checked it and it seemed to work. What problems do you see with this case?
On its own it just doesn't tell you whether or not LOCK_MAND is set. But I guess you can still get that out of /proc/locks.
To be honest I don't really know whether LOCK_MAND works or is used.
--b.
Quoted 55 lines · On Tue, 2 Sep 2014 15:43:00 -0400 "J. Bruce Fields"…
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?After a fork, two processes "own" the lock, right?:
int main(int argc, char *argv[]) { int fd, ret; fd = open(argv[1], O_RDWR); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); ret = fork(); if (ret == -1) err(1, "flock"); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); printf("%d got exclusive lock\n", getpid()); sleep(1000); } $ touch TMP $ ./test TMP 15882 got exclusive lock 15883 got exclusive lock ^C
Quoted 2 lines
I may misunderstand what you're doing.
Yeah, I don't understand either.
Flock locks are owned by the file description. The task that set them is really irrelevant once they are set.
In the second flock() call there, you're just "modifying" an existing lock (which turns out to be a noop here).
So, I don't quite understand the problem this solves. I get that you're trying to reestablish the flock "state" after a checkpoint/restore event, but why does it matter what task actually sets the locks as long as they're set on the correct set of fds?
Quoted 25 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
With
LOCK_SHthis doesn't work. Trying to drop the
lock doesn't work either, asflock(LOCK_UN)reports 0 in both cases:
if the file is locked and if it is not.That said, I'd like to propose the
LOCK_TESTflag to the flock call, that would check whether the lock of the given type (LOCK_SHorLOCK_EX) exists on the file we test. It's not the same as the existing in-kernelFL_ACCESSflag, which checks whether the new lock is possible, but it's a newFL_TESTflag, that checks whether the existing lock is there.Quoted 8 lines
Quoted 5 lines
Quoted 1 line
What do you think?
I guess I can't see anything really wrong with it.
It ignores the (poorly documented)
LOCK_MANDcase, but maybe that's OK.I actually checked it and it seemed to work. What problems do you see with this case?
On its own it just doesn't tell you whether or not
LOCK_MANDis set. But I guess you can still get that out of/proc/locks.To be honest I don't really know whether
LOCK_MANDworks or is used.--b.
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 66 lines · Jeff Layton
Quoted 55 lines · On Tue, 2 Sep 2014 15:43:00 -0400 "J. Bruce Fields" <[email protected]>…
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?After a fork, two processes "own" the lock, right?:
int main(int argc, char *argv[]) { int fd, ret; fd = open(argv[1], O_RDWR); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); ret = fork(); if (ret == -1) err(1, "flock"); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); printf("%d got exclusive lock\n", getpid()); sleep(1000); } $ touch TMP $ ./test TMP 15882 got exclusive lock 15883 got exclusive lock ^CQuoted 2 lines
I may misunderstand what you're doing.
Yeah, I don't understand either.
Flock locks are owned by the file description. The task that set them is really irrelevant once they are set.
Quoted 7 lines
In the second
flock()call there, you're just "modifying" an existing lock (which turns out to be a noop here).So, I don't quite understand the problem this solves. I get that you're trying to reestablish the flock "state" after a checkpoint/restore event, but why does it matter what task actually sets the locks as long as they're set on the correct set of fds?
Sorry for confusion. Let me try to explain it more clearly.
First, what I meant talking about two LOCK_EX locks. Let's consider this scenario:
pid = fork()
fd = open("/foo"); /* both parent and child has _different_ files */ if (pid == 0)
/* child only */ flock(fd, LOCK_EX);
at this point we have two different files pointing to "/foo" and only one of them has LOCK_EX on it. So if try to LOCK_EX it again, only at child's file this would succeed. So we can distinguish which file is locked using this method.
Now, what problem this patch is trying to solve. It's quite tricky, but still. Let's imagine this scenario:
pid = fork();
fd = open("/foo"); /* yet again -- two different files */
if (pid == 0) {
flock(fd, LOCK_SH);
pid2 = fork();
if (pid2 != 0)
exit(0);
}at this point we have:
task A -- the original task with file "/foo" opened
task B -- the first child, that exited at the end
task C -- the 2nd child, that "inherited" a file with the lock from B
Note, that file at A and file at C are two different files (struct file-s). And it's only the C's one that is locked.
The problem is that the /proc/locks shows the pid of B in this lock's owner field. And we have no glue to find out who the real lock owner is using the /proc/locks.
If we try to do the trickery like the one we did with LOCK_EX above, this is what we would get.
If putting the 2nd LOCK_SH from A and from C, both attempts would succeed, so this is not the solution.
If we try to LOCK_EX from A and C, only C would succeed, so this seem to be the solution, but it's actually not. If there's another pair of A' and C' tasks holding the same "/foo" and having the LOCK_SH on C', this trick would stop working as none of the tasks would be able to put such lock on this file.
Thus, we need some way to find out whether a task X has a lock on file F. This patch is one of the ways of doing this.
Hope this explanation is more clear.
Quoted 27 lines
Quoted 25 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
With
LOCK_SHthis doesn't work. Trying to drop the
lock doesn't work either, asflock(LOCK_UN)reports 0 in both cases:
if the file is locked and if it is not.That said, I'd like to propose the
LOCK_TESTflag to the flock call, that would check whether the lock of the given type (LOCK_SHorLOCK_EX) exists on the file we test. It's not the same as the existing in-kernelFL_ACCESSflag, which checks whether the new lock is possible, but it's a newFL_TESTflag, that checks whether the existing lock is there.Quoted 8 lines
Quoted 5 lines
Quoted 1 line
What do you think?
I guess I can't see anything really wrong with it.
It ignores the (poorly documented)
LOCK_MANDcase, but maybe that's OK.I actually checked it and it seemed to work. What problems do you see with this case?
On its own it just doesn't tell you whether or not
LOCK_MANDis set. But I guess you can still get that out of/proc/locks.To be honest I don't really know whether
LOCK_MANDworks or is used.--b.
Quoted 131 lines · Pavel Emelyanov
Quoted 66 lines · Jeff Layton
Quoted 55 lines · On Tue, 2 Sep 2014 15:43:00 -0400 "J. Bruce Fields"…
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?After a fork, two processes "own" the lock, right?:
int main(int argc, char *argv[]) { int fd, ret; fd = open(argv[1], O_RDWR); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); ret = fork(); if (ret == -1) err(1, "flock"); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); printf("%d got exclusive lock\n", getpid()); sleep(1000); } $ touch TMP $ ./test TMP 15882 got exclusive lock 15883 got exclusive lock ^CQuoted 2 lines
I may misunderstand what you're doing.
Yeah, I don't understand either.
Flock locks are owned by the file description. The task that set them is really irrelevant once they are set.
Quoted 7 lines
In the second
flock()call there, you're just "modifying" an existing lock (which turns out to be a noop here).So, I don't quite understand the problem this solves. I get that you're trying to reestablish the flock "state" after a checkpoint/restore event, but why does it matter what task actually sets the locks as long as they're set on the correct set of fds?
Sorry for confusion. Let me try to explain it more clearly.
First, what I meant talking about two
LOCK_EXlocks. Let's consider this scenario:pid =
fork()
fd =open("/foo"); /* both parent and child has _different_ files */ if (pid == 0)/* child only */ flock(fd, LOCK_EX);at this point we have two different files pointing to "/foo" and only one of them has
LOCK_EXon it. So if try toLOCK_EXit again, only at child's file this would succeed. So we can distinguish which file is locked using this method.Now, what problem this patch is trying to solve. It's quite tricky, but still. Let's imagine this scenario:
pid =
fork();
fd =open("/foo"); /* yet again -- two different files */if (pid == 0) { flock(fd, LOCK_SH); pid2 = fork(); if (pid2 != 0) exit(0); }at this point we have:
task A -- the original task with file "/foo" opened
task B -- the first child, that exited at the end
task C -- the 2nd child, that "inherited" a file with the lock from BNote, that file at A and file at C are two different files (struct file-s). And it's only the C's one that is locked.
The problem is that the
/proc/locksshows the pid of B in this lock's owner field. And we have no glue to find out who the real lock owner is using the/proc/locks.If we try to do the trickery like the one we did with
LOCK_EXabove, this is what we would get.If putting the 2nd
LOCK_SHfrom A and from C, both attempts would succeed, so this is not the solution.If we try to
LOCK_EXfrom A and C, only C would succeed, so this seem to be the solution, but it's actually not. If there's another pair of A' and C' tasks holding the same "/foo" and having theLOCK_SHon C', this trick would stop working as none of the tasks would be able to put such lock on this file.
Quoted 4 lines
Thus, we need some way to find out whether a task X has a lock on file F. This patch is one of the ways of doing this.
Hope this explanation is more clear.
Thanks, I think I understand.
Remind me how you figure out which file descriptors point to the same file description (struct file)?
--b.
On 09/03/2014 07:44 PM, J. Bruce Fields wrote:
...
Quoted 6 lines
Quoted 1 line
Hope this explanation is more clear.
Thanks, I think I understand.
Remind me how you figure out which file descriptors point to the same file description (struct file)?
We do it with the help of kcmp() syscall:
https://github.com/cyrillos/linux-2.6/commit/951bc60c6a
Thanks,
Pavel
Quoted 131 lines · On Wed, 3 Sep 2014 18:38:24 +0400 Pavel Emelyanov <[email protected]> wrote:
Quoted 66 lines · Jeff Layton
Quoted 55 lines · On Tue, 2 Sep 2014 15:43:00 -0400 "J. Bruce Fields" <[email protected]>…
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?After a fork, two processes "own" the lock, right?:
int main(int argc, char *argv[]) { int fd, ret; fd = open(argv[1], O_RDWR); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); ret = fork(); if (ret == -1) err(1, "flock"); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); printf("%d got exclusive lock\n", getpid()); sleep(1000); } $ touch TMP $ ./test TMP 15882 got exclusive lock 15883 got exclusive lock ^CQuoted 2 lines
I may misunderstand what you're doing.
Yeah, I don't understand either.
Flock locks are owned by the file description. The task that set them is really irrelevant once they are set.
Quoted 7 lines
In the second
flock()call there, you're just "modifying" an existing lock (which turns out to be a noop here).So, I don't quite understand the problem this solves. I get that you're trying to reestablish the flock "state" after a checkpoint/restore event, but why does it matter what task actually sets the locks as long as they're set on the correct set of fds?
Sorry for confusion. Let me try to explain it more clearly.
First, what I meant talking about two
LOCK_EXlocks. Let's consider this scenario:pid =
fork()
fd =open("/foo"); /* both parent and child has _different_ files */ if (pid == 0)/* child only */ flock(fd, LOCK_EX);at this point we have two different files pointing to "/foo" and only one of them has
LOCK_EXon it. So if try toLOCK_EXit again, only at child's file this would succeed. So we can distinguish which file is locked using this method.Now, what problem this patch is trying to solve. It's quite tricky, but still. Let's imagine this scenario:
pid =
fork();
fd =open("/foo"); /* yet again -- two different files */if (pid == 0) { flock(fd, LOCK_SH); pid2 = fork(); if (pid2 != 0) exit(0); }at this point we have:
task A -- the original task with file "/foo" opened
task B -- the first child, that exited at the end
task C -- the 2nd child, that "inherited" a file with the lock from BNote, that file at A and file at C are two different files (struct file-s). And it's only the C's one that is locked.
The problem is that the
/proc/locksshows the pid of B in this lock's owner field. And we have no glue to find out who the real lock owner is using the/proc/locks.If we try to do the trickery like the one we did with
LOCK_EXabove, this is what we would get.If putting the 2nd
LOCK_SHfrom A and from C, both attempts would succeed, so this is not the solution.If we try to
LOCK_EXfrom A and C, only C would succeed, so this seem to be the solution, but it's actually not. If there's another pair of A' and C' tasks holding the same "/foo" and having theLOCK_SHon C', this trick would stop working as none of the tasks would be able to put such lock on this file.
Quoted 5 lines
Thus, we need some way to find out whether a task X has a lock on file F. This patch is one of the ways of doing this.
Hope this explanation is more clear.
Yes, thanks for clarifying.
I think we do need to be a bit careful when describing this though.
flock locks are not owned by tasks, but by the file description. So you can't really tell whether task X has a lock on file F. Several tasks could have a reference to file F and none of them has any more "claim" to a lock on that file than another (at least from an API standpoint).
What your patch really does is tell you whether that file description has a particular type of lock set on it.
Like Bruce, I think this looks fairly reasonable. That said, I had to go through a bunch of API gyrations recently when getting the OFD lock patches merged. It would be good to accompany your kernel patch with glibc and manpage patches as well so we can make sure we have the design settled before merging anything.
Sound OK?
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 144 lines · Jeff Layton
Quoted 131 lines · On Wed, 3 Sep 2014 18:38:24 +0400 Pavel Emelyanov…
Quoted 66 lines · Jeff Layton
Quoted 55 lines · On Tue, 2 Sep 2014 15:43:00 -0400 "J. Bruce Fields"…
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?After a fork, two processes "own" the lock, right?:
int main(int argc, char *argv[]) { int fd, ret; fd = open(argv[1], O_RDWR); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); ret = fork(); if (ret == -1) err(1, "flock"); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); printf("%d got exclusive lock\n", getpid()); sleep(1000); } $ touch TMP $ ./test TMP 15882 got exclusive lock 15883 got exclusive lock ^CQuoted 2 lines
I may misunderstand what you're doing.
Yeah, I don't understand either.
Flock locks are owned by the file description. The task that set them is really irrelevant once they are set.
Quoted 7 lines
In the second
flock()call there, you're just "modifying" an existing lock (which turns out to be a noop here).So, I don't quite understand the problem this solves. I get that you're trying to reestablish the flock "state" after a checkpoint/restore event, but why does it matter what task actually sets the locks as long as they're set on the correct set of fds?
Sorry for confusion. Let me try to explain it more clearly.
First, what I meant talking about two
LOCK_EXlocks. Let's consider this scenario:pid =
fork()
fd =open("/foo"); /* both parent and child has _different_ files */ if (pid == 0)/* child only */ flock(fd, LOCK_EX);at this point we have two different files pointing to "/foo" and only one of them has
LOCK_EXon it. So if try toLOCK_EXit again, only at child's file this would succeed. So we can distinguish which file is locked using this method.Now, what problem this patch is trying to solve. It's quite tricky, but still. Let's imagine this scenario:
pid =
fork();
fd =open("/foo"); /* yet again -- two different files */if (pid == 0) { flock(fd, LOCK_SH); pid2 = fork(); if (pid2 != 0) exit(0); }at this point we have:
task A -- the original task with file "/foo" opened
task B -- the first child, that exited at the end
task C -- the 2nd child, that "inherited" a file with the lock from BNote, that file at A and file at C are two different files (struct file-s). And it's only the C's one that is locked.
The problem is that the
/proc/locksshows the pid of B in this lock's owner field. And we have no glue to find out who the real lock owner is using the/proc/locks.If we try to do the trickery like the one we did with
LOCK_EXabove, this is what we would get.If putting the 2nd
LOCK_SHfrom A and from C, both attempts would succeed, so this is not the solution.If we try to
LOCK_EXfrom A and C, only C would succeed, so this seem to be the solution, but it's actually not. If there's another pair of A' and C' tasks holding the same "/foo" and having theLOCK_SHon C', this trick would stop working as none of the tasks would be able to put such lock on this file.Quoted 5 lines
Thus, we need some way to find out whether a task X has a lock on file F. This patch is one of the ways of doing this.
Hope this explanation is more clear.
Yes, thanks for clarifying.
I think we do need to be a bit careful when describing this though.
Quoted 7 lines
flock locks are not owned by tasks, but by the file description. So you can't really tell whether task X has a lock on file F. Several tasks could have a reference to file F and none of them has any more "claim" to a lock on that file than another (at least from an API standpoint).
What your patch really does is tell you whether that file description has a particular type of lock set on it.
Exactly.
Quoted 7 lines
Like Bruce, I think this looks fairly reasonable. That said, I had to go through a bunch of API gyrations recently when getting the OFD lock patches merged. It would be good to accompany your kernel patch with glibc and manpage patches as well so we can make sure we have the design settled before merging anything.
Sound OK?
Sure! But I think glibc and man-pages people would first want the kernel part to get finished, as it's the part that mostly drives the API. Since the linux-api@ is in Cc for this patch, what else would you suggest me to do to keep the process moving?
Thanks,
Pavel
Quoted 163 lines · On Wed, 3 Sep 2014 20:00:02 +0400 Pavel Emelyanov…
Quoted 144 lines · Jeff Layton
Quoted 131 lines · On Wed, 3 Sep 2014 18:38:24 +0400 Pavel Emelyanov…
Quoted 66 lines · Jeff Layton
Quoted 55 lines · On Tue, 2 Sep 2014 15:43:00 -0400 "J. Bruce Fields"…
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?After a fork, two processes "own" the lock, right?:
int main(int argc, char *argv[]) { int fd, ret; fd = open(argv[1], O_RDWR); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); ret = fork(); if (ret == -1) err(1, "flock"); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); printf("%d got exclusive lock\n", getpid()); sleep(1000); } $ touch TMP $ ./test TMP 15882 got exclusive lock 15883 got exclusive lock ^CQuoted 2 lines
I may misunderstand what you're doing.
Yeah, I don't understand either.
Flock locks are owned by the file description. The task that set them is really irrelevant once they are set.
Quoted 7 lines
In the second
flock()call there, you're just "modifying" an existing lock (which turns out to be a noop here).So, I don't quite understand the problem this solves. I get that you're trying to reestablish the flock "state" after a checkpoint/restore event, but why does it matter what task actually sets the locks as long as they're set on the correct set of fds?
Sorry for confusion. Let me try to explain it more clearly.
First, what I meant talking about two
LOCK_EXlocks. Let's consider this scenario:pid =
fork()
fd =open("/foo"); /* both parent and child has _different_ files */ if (pid == 0)/* child only */ flock(fd, LOCK_EX);at this point we have two different files pointing to "/foo" and only one of them has
LOCK_EXon it. So if try toLOCK_EXit again, only at child's file this would succeed. So we can distinguish which file is locked using this method.Now, what problem this patch is trying to solve. It's quite tricky, but still. Let's imagine this scenario:
pid =
fork();
fd =open("/foo"); /* yet again -- two different files */if (pid == 0) { flock(fd, LOCK_SH); pid2 = fork(); if (pid2 != 0) exit(0); }at this point we have:
task A -- the original task with file "/foo" opened
task B -- the first child, that exited at the end
task C -- the 2nd child, that "inherited" a file with the lock from BNote, that file at A and file at C are two different files (struct file-s). And it's only the C's one that is locked.
The problem is that the
/proc/locksshows the pid of B in this lock's owner field. And we have no glue to find out who the real lock owner is using the/proc/locks.If we try to do the trickery like the one we did with
LOCK_EXabove, this is what we would get.If putting the 2nd
LOCK_SHfrom A and from C, both attempts would succeed, so this is not the solution.If we try to
LOCK_EXfrom A and C, only C would succeed, so this seem to be the solution, but it's actually not. If there's another pair of A' and C' tasks holding the same "/foo" and having theLOCK_SHon C', this trick would stop working as none of the tasks would be able to put such lock on this file.Quoted 5 lines
Thus, we need some way to find out whether a task X has a lock on file F. This patch is one of the ways of doing this.
Hope this explanation is more clear.
Yes, thanks for clarifying.
I think we do need to be a bit careful when describing this though.
Quoted 7 lines
flock locks are not owned by tasks, but by the file description. So you can't really tell whether task X has a lock on file F. Several tasks could have a reference to file F and none of them has any more "claim" to a lock on that file than another (at least from an API standpoint).
What your patch really does is tell you whether that file description has a particular type of lock set on it.
Exactly.
Quoted 7 lines
Like Bruce, I think this looks fairly reasonable. That said, I had to go through a bunch of API gyrations recently when getting the OFD lock patches merged. It would be good to accompany your kernel patch with glibc and manpage patches as well so we can make sure we have the design settled before merging anything.
Sound OK?
Quoted 8 lines
Sure! But I think glibc and man-pages people would first want the kernel part to get finished, as it's the part that mostly drives the API. Since the linux-api@ is in Cc for this patch, what else would you suggest me to do to keep the process moving?
Thanks,
Pavel
(cc'ing Michael Kerrisk, the manpages maintainer)
Michael had good suggestions for me when I was doing the OFD lock work. I'd also consider cc'ing the glibc development list.
Cheers,
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 172 lines · Jeff Layton
Quoted 168 lines · On Wed, 3 Sep 2014 20:00:02 +0400 Pavel Emelyanov…
Quoted 144 lines · Jeff Layton
Quoted 131 lines · On Wed, 3 Sep 2014 18:38:24 +0400 Pavel Emelyanov…
Quoted 66 lines · Jeff Layton
Quoted 49 lines · On Tue, 2 Sep 2014 15:43:00 -0400 "J. Bruce Fields"…
Quoted 19 lines · Pavel Emelyanov
Quoted 18 lines · J. Bruce Fields
Quoted 17 lines · Pavel Emelyanov
Hi,
There's a problem with getting information about who has a flock on a specific file. The thing is that the "owner" field, that is shown in
/proc/locksis the pid of the task who created the flock, not the one who _may_ hold it.If the flock creator shared the file with some other task (by forking or via
scm_rights) and then died or closed the file, the information shown in proc no longer corresponds to the reality.This is critical for CRIU project, that tries to dump (and restore) the state of running tasks. For example, let's take two tasks A and B both opened a file "/foo", one of tasks places a
LOCK_SHlock on the file and then "obfuscated" the owner field in/proc/locks. After this we have no ways to find out who is the lock holder.Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
I'd like to note, that for
LOCK_EXthis problem is not critical -- we may go to both tasks and "ask" them toLOCK_EXthe file again (we can do it in CRIU, I can tell more if required). The one who succeeds is the lock holder.It could be both, actually, right?
Two succeeding with
LOCK_EX? AFAIU no. Am I missing something?After a fork, two processes "own" the lock, right?:
int
main(int argc, char *argv[]){ int fd, ret; fd = open(argv[1], O_RDWR); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); ret = fork(); if (ret == -1) err(1, "flock"); ret = flock(fd, LOCK_EX); if (ret) err(1, "flock"); printf("%d got exclusive lock\n", getpid()); sleep(1000);}
Quoted 8 lines
$ touch TMP $ ./test TMP 15882 got exclusive lock 15883 got exclusive lock ^CI may misunderstand what you're doing.
Yeah, I don't understand either.
Flock locks are owned by the file description. The task that set them is really irrelevant once they are set.
Quoted 7 lines
In the second
flock()call there, you're just "modifying" an existing lock (which turns out to be a noop here).So, I don't quite understand the problem this solves. I get that you're trying to reestablish the flock "state" after a checkpoint/restore event, but why does it matter what task actually sets the locks as long as they're set on the correct set of fds?
Sorry for confusion. Let me try to explain it more clearly.
First, what I meant talking about two
LOCK_EXlocks. Let's consider this scenario:pid =
fork()
fd =open("/foo"); /* both parent and child has _different_ files */ if (pid == 0)
/* child only */
flock(fd, LOCK_EX);at this point we have two different files pointing to "/foo" and only one of them has
LOCK_EXon it. So if try toLOCK_EXit again, only at child's file this would succeed. So we can distinguish which file is locked using this method.Now, what problem this patch is trying to solve. It's quite tricky, but still. Let's imagine this scenario:
pid =
fork();
fd =open("/foo"); /* yet again -- two different files */if (pid == 0) { flock(fd, LOCK_SH); pid2 = fork(); if (pid2 != 0) exit(0); }at this point we have:
task A -- the original task with file "/foo" opened
task B -- the first child, that exited at the end
task C -- the 2nd child, that "inherited" a file with the lock from BNote, that file at A and file at C are two different files (struct file-s). And it's only the C's one that is locked.
The problem is that the
/proc/locksshows the pid of B in this lock's owner field. And we have no glue to find out who the real lock owner is using the/proc/locks.If we try to do the trickery like the one we did with
LOCK_EXabove, this is what we would get.If putting the 2nd
LOCK_SHfrom A and from C, both attempts would succeed, so this is not the solution.If we try to
LOCK_EXfrom A and C, only C would succeed, so this seem to be the solution, but it's actually not. If there's another pair of A' and C' tasks holding the same "/foo" and having theLOCK_SHon C', this trick would stop working as none of the tasks would be able to put such lock on this file.Quoted 5 lines
Thus, we need some way to find out whether a task X has a lock on file F. This patch is one of the ways of doing this.
Hope this explanation is more clear.
Yes, thanks for clarifying.
I think we do need to be a bit careful when describing this though.
Quoted 7 lines
flock locks are not owned by tasks, but by the file description. So you can't really tell whether task X has a lock on file F. Several tasks could have a reference to file F and none of them has any more "claim" to a lock on that file than another (at least from an API standpoint).
What your patch really does is tell you whether that file description has a particular type of lock set on it.
Exactly.
Quoted 7 lines
Like Bruce, I think this looks fairly reasonable. That said, I had to go through a bunch of API gyrations recently when getting the OFD lock patches merged. It would be good to accompany your kernel patch with glibc and manpage patches as well so we can make sure we have the design settled before merging anything.
Sound OK?
Sure! But I think glibc and man-pages people would first want the kernel part to get finished, as it's the part that mostly drives the API. Since the linux-api@ is in Cc for this patch, what else would you suggest me to do to keep the process moving?
Quoted 8 lines
Quoted 3 lines
Thanks,
Pavel(cc'ing Michael Kerrisk, the manpages maintainer)
Michael had good suggestions for me when I was doing the OFD lock work. I'd also consider cc'ing the glibc development list.
I would suggest writing up a short description of the exact semantics of your proposal. That way reviewers can decide whether the semantics make sense and then check whether the code matches the description.
This could take the form of text that would go in the appropriate manpage.
--Andy
Quoted 7 lines · Pavel Emelyanov
Quoted 3 lines
Would it make sense to return the lock type held instead, so you could do one
flock(fd, LOCK_TEST)instead offlock(fd, LOCK_TEST|LOCK_SH)andflock(fd, LOCK_TEST|LOCK_EX)?Well, in our case we parse
/proc/locksanyway to see what files at least to test for being locked. But what you propose looks even better. I'll look what can be done here.
Actually I think I prefer your version. It seems cleaner to define LOCK_TEST as returning the same result as you'd get if you actually tried the lock, just without applying the lock. It avoids having a different return-value convention for this one command. It might avoid some ambiguity in cases where the flock might be denied for reasons other than a conflicting flock (e.g. on NFS where flocks and fcntl locks conflict). It's closer to what GETLK does in the fcntl case.
--b.
Quoted 9 lines · On Tue, 9 Sep 2014 12:18:21 -0400 "J. Bruce Fields" <[email protected]>…
Quoted 7 lines · Pavel Emelyanov
Quoted 3 lines
Would it make sense to return the lock type held instead, so you could do one
flock(fd, LOCK_TEST)instead offlock(fd, LOCK_TEST|LOCK_SH)andflock(fd, LOCK_TEST|LOCK_EX)?Well, in our case we parse
/proc/locksanyway to see what files at least to test for being locked. But what you propose looks even better. I'll look what can be done here.
Quoted 8 lines
Actually I think I prefer your version. It seems cleaner to define
LOCK_TESTas returning the same result as you'd get if you actually tried the lock, just without applying the lock. It avoids having a different return-value convention for this one command. It might avoid some ambiguity in cases where the flock might be denied for reasons other than a conflicting flock (e.g. on NFS where flocks and fcntl locks conflict). It's closer to what GETLK does in the fcntl case.
Yeah, I think I agree here too. Best to keep the interface as simple as possible, and the principle of least surprise would dictate that the return value match how other flock() calls work.
I would still like to see a proposed manpage update for it. For bonus points, writing a section on flock() for the glibc manual might help get that piece merged as well.
It was my experience that getting the small header file #defines into glibc for OFD locks was much more difficult than the kernel piece. YMMV of course, but getting the glibc folks to buy into the idea ahead of time would be good if possible.
Signature · 1 line
Jeff Layton <[email protected]>