def find_inodes_in_use(fds):
    """
    Find which of these inodes are in use, and give their open modes.

    Does not count the passed fds as an use of the inode they point to,
    but if the current process has the same inodes open with different
    file descriptors these will be listed.

    Looks at /proc/*/fd and /proc/*/map_files (Linux 3.3).
    Conceivably there are other uses we're missing, to be foolproof
    will require support in btrfs itself; a share-same-range ioctl
    would work well.
    """

    self_pid = os.getpid()
    id_fd_assoc = collections.defaultdict(list)

    for fd in fds:
        st = os.fstat(fd)
        id_fd_assoc[(st.st_dev, st.st_ino)].append(fd)

    def st_id_candidates(it):
        # map proc paths to stat identifiers (devno and ino)
        for proc_path in it:
            try:
                st = os.stat(proc_path)
            except OSError as e:
                # glob opens directories during matching,
                # and other processes might close their fds in the meantime.
                # This isn't a problem for the immutable-locked use case.
                # ESTALE could happen with NFS or Docker
                if e.errno in (errno.ENOENT, errno.ESTALE):
                    continue
                raise

            st_id = (st.st_dev, st.st_ino)
            if st_id not in id_fd_assoc:
                continue

            yield proc_path, st_id

    for proc_path, st_id in st_id_candidates(glob.glob('/proc/[1-9]*/fd/*')):
        other_pid, other_fd = map(
            int, PROC_PATH_RE.match(proc_path).groups())
        original_fds = id_fd_assoc[st_id]
        if other_pid == self_pid:
            if other_fd in original_fds:
                continue

        use_info = proc_use_info(proc_path)
        if not use_info:
            continue

        for fd in original_fds:
            yield (fd, use_info)

    # Requires Linux 3.3
    for proc_path, st_id in st_id_candidates(
        glob.glob('/proc/[1-9]*/map_files/*')
    ):
        use_info = proc_use_info(proc_path)
        if not use_info:
            continue

        original_fds = id_fd_assoc[st_id]
        for fd in original_fds:
            yield (fd, use_info)
Find which of these inodes are in use, and give their open modes.

    Does not count the passed fds as an use of the inode they point to,
    but if the current process has the same inodes open with different
    file descriptors these will be listed.

    Looks at /proc/*/fd and /proc/*/map_files (Linux 3.3).
    Conceivably there are other uses we're missing, to be foolproof
    will require support in btrfs itself; a share-same-range ioctl
    would work well.