[CRIU] [PATCH] locks: fix up a device returned by stat() for btrfs (v4)
Andrew Vagin
avagin at openvz.org
Wed Sep 3 12:40:33 PDT 2014
BTRFS returns subvolume dev-id instead of superblock dev-id,
in such case return device obtained from mountinfo (ie subvolume0).
v2: fix up devices only for btrfs files.
v3: use phys_stat_dev_match instead of phys_stat_resolve_dev
v4: fix cosmetic whims
Reported-by: Mr Jenkins
Signed-off-by: Andrew Vagin <avagin at openvz.org>
---
file-lock.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 52 insertions(+), 4 deletions(-)
diff --git a/file-lock.c b/file-lock.c
index b6a511f..b351f86 100644
--- a/file-lock.c
+++ b/file-lock.c
@@ -9,7 +9,10 @@
#include "cr_options.h"
#include "fdset.h"
#include "files.h"
+#include "fs-magic.h"
#include "image.h"
+#include "mount.h"
+#include "proc_parse.h"
#include "servicefd.h"
#include "file-lock.h"
#include "parasite.h"
@@ -121,10 +124,51 @@ err:
return ret;
}
-static inline bool lock_file_match(struct file_lock *fl, struct fd_parms *p)
+static int lock_btrfs_file_match(pid_t pid, int fd, struct file_lock *fl, struct fd_parms *p)
{
- return fl->i_no == p->stat.st_ino &&
- makedev(fl->maj, fl->min) == p->stat.st_dev;
+ int phys_dev = MKKDEV(fl->maj, fl->min);
+ char link[PATH_MAX], t[32];
+ struct ns_id *ns;
+ int ret;
+
+ snprintf(t, sizeof(t), "/proc/%d/fd/%d", pid, fd);
+ ret = readlink(t, link, sizeof(link)) - 1;
+ if (ret < 0) {
+ pr_perror("Can't read link of fd %d", fd);
+ return -1;
+ } else if ((size_t)ret == sizeof(link)) {
+ pr_err("Buffer for read link of fd %d is too small\n", fd);
+ return -1;
+ }
+ link[ret] = 0;
+
+ ns = lookup_nsid_by_mnt_id(p->mnt_id);
+ return phys_stat_dev_match(p->stat.st_dev, phys_dev, ns, link);
+}
+
+static inline int lock_file_match(pid_t pid, int fd, struct file_lock *fl, struct fd_parms *p)
+{
+ dev_t dev = p->stat.st_dev;
+
+ if (fl->i_no != p->stat.st_ino)
+ return 0;
+
+ /*
+ * Get the right devices for BTRFS. Look at phys_stat_resolve_dev()
+ * for more details.
+ */
+ if (p->fs_type == BTRFS_SUPER_MAGIC) {
+ if (p->mnt_id != -1) {
+ struct mount_info *m;
+
+ m = lookup_mnt_id(p->mnt_id);
+ BUG_ON(m == NULL);
+ dev = kdev_to_odev(m->s_dev);
+ } else /* old kernel */
+ return lock_btrfs_file_match(pid, fd, fl, p);
+ }
+
+ return makedev(fl->maj, fl->min) == dev;
}
static int lock_check_fd(int lfd, struct file_lock *fl)
@@ -164,9 +208,13 @@ static int lock_check_fd(int lfd, struct file_lock *fl)
int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
{
struct file_lock *fl;
+ int ret;
list_for_each_entry(fl, &file_lock_list, list) {
- if (!lock_file_match(fl, p))
+ ret = lock_file_match(pid->real, fd, fl, p);
+ if (ret < 0)
+ return -1;
+ if (ret == 0)
continue;
if (!opts.handle_file_locks) {
--
1.9.3
More information about the CRIU
mailing list