[CRIU] [PATCH 3/6] locks: Don't dump locks in per-task manner (v2)
Pavel Emelyanov
xemul at parallels.com
Thu Aug 28 07:40:23 PDT 2014
On 08/28/2014 04:51 PM, Andrew Vagin wrote:
> On Tue, Aug 26, 2014 at 09:30:40PM +0400, Pavel Emelyanov wrote:
>> We have a problem with file locks (bug #2512) -- the /proc/locks
>> file shows the ID of lock creator, not the owner. Thus, if the
>> creator died, but holder is still alive, criu fails to dump the
>> lock held by latter task.
>>
>> The proposal is to find who _might_ hold the lock by checking
>> for dev:inode pairs on lock vs file descriptors being dumped.
>> If the creator of the lock is still alive, then he will take
>> the priority.
>>
>> One thing to note about flocks -- these belong to file entries,
>> not to tasks. Thus, when we meet one, we should check whether
>> the flock is really held by task's FD by trying to set yet
>> another one. In case of success -- lock really belongs to fd
>> we dump, in case it doesn't trylock should fail.
>>
>> At the very end -- walk the list of locks and dump them all at
>> once, which is possible by merge of per-task file-locks images
>> into one global one.
>>
>> Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
>> ---
>
> ...
>
>> +int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
>> +{
>> + struct file_lock *fl;
>> +
>> + list_for_each_entry(fl, &file_lock_list, list) {
>> + if (!lock_file_match(fl, p))
>> + continue;
>> +
>> + if (fl->fl_kind == FL_POSIX) {
>> + /*
>> + * POSIX locks cannot belong to anyone
>> + * but creator.
>> + */
>> + if (fl->fl_owner != pid->real)
>> + continue;
>> + } else /* fl->fl_kind == FL_FLOCK */ {
>> + int ret;
>> +
>> + /*
>> + * FLOCKs can be inherited across fork,
>> + * thus we can have any task as lock
>> + * owner. But the creator is preferred
>> + * anyway.
>> + */
>> +
>> + if (fl->fl_owner != pid->real &&
>> + fl->real_owner != -1)
>> + continue;
>> +
>> + pr_debug("Checking lock holder %d:%d\n", pid->real, fd);
>> + ret = flock(lfd, LOCK_EX | LOCK_NB);
>
> I don't understand how do you find descriptors, which hold shared locks.
If EX lock is approved, this denotes that the current FD holds one,
be it SH or EX doesn't matter.
> """
> LOCK_SH Place a shared lock. More than one process may hold a shared
> lock for a given file at a given time.
>
> LOCK_EX Place an exclusive lock. Only one process may hold an
> exclusive lock for a given file at a given time.
> """
>
>> + pr_debug(" `- %d/%d\n", ret, errno);
>> + if (ret != 0) {
>> + if (errno != EAGAIN) {
>> + pr_err("Bogus lock test result %d\n", ret);
>> + return -1;
>> + }
>> +
>> + continue;
>> + }
>> +
>> + /*
>> + * The ret == 0 means, that new lock doesn't conflict
>> + * with any others on the file. But since we do know,
>> + * that there should be some other one (file is found
>> + * in /proc/locks), it means that the lock is already
>> + * on file pointed by fd.
>> + */
>> + }
>> +
>> + fl->real_owner = pid->virt;
>> + fl->owners_fd = fd;
>> +
>> + pr_info("Found lock entry %d.%d %d vs %d\n",
>> + pid->real, pid->virt, fd,
>> + fl->fl_owner);
>> + }
> .
>
More information about the CRIU
mailing list