[CRIU] [PATCH 3/6] locks: Don't dump locks in per-task manner (v2)

Andrew Vagin avagin at parallels.com
Thu Aug 28 05:51:38 PDT 2014


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.

"""
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