Ticket #13795: fixlocks.patch

File fixlocks.patch, 4.9 KB (added by pulkomandy, 3 years ago)

Tentative fix (incomplete)

  • src/system/kernel/fs/vfs.cpp

    diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp
    index 35b7d908c0..5572964562 100644
    a b struct advisory_lock : public DoublyLinkedListLinkImpl<advisory_lock> {  
    173173    list_link       link;
    174174    team_id         team;
    175175    pid_t           session;
     176    int             fd;
    176177    off_t           start;
    177178    off_t           end;
    178179    bool            shared;
    test_advisory_lock(struct vnode* vnode, struct flock* flock)  
    16261627    if \a flock is NULL.
    16271628*/
    16281629static status_t
    1629 release_advisory_lock(struct vnode* vnode, struct flock* flock)
     1630release_advisory_lock(struct vnode* vnode, int fd, struct flock* flock)
    16301631{
    16311632    FUNCTION(("release_advisory_lock(vnode = %p, flock = %p)\n", vnode, flock));
    16321633
    release_advisory_lock(struct vnode* vnode, struct flock* flock)  
    16451646        struct advisory_lock* lock = iterator.Next();
    16461647        bool removeLock = false;
    16471648
    1648         if (lock->session == session)
     1649        if (lock->session == session && lock->fd == fd)
    16491650            removeLock = true;
    1650         else if (lock->team == team && advisory_lock_intersects(lock, flock)) {
     1651        else if (lock->team == team && lock->fd == fd
     1652                && advisory_lock_intersects(lock, flock)) {
    16511653            bool endsBeyond = false;
    16521654            bool startsBefore = false;
    16531655            if (flock != NULL) {
    release_advisory_lock(struct vnode* vnode, struct flock* flock)  
    16781680
    16791681                secondLock->team = lock->team;
    16801682                secondLock->session = lock->session;
     1683                secondLock->fd = lock->fd;
    16811684                // values must already be normalized when getting here
    16821685                secondLock->start = flock->l_start + flock->l_len;
    16831686                secondLock->end = lock->end;
    release_advisory_lock(struct vnode* vnode, struct flock* flock)  
    17331736    will wait for the lock to become available, if there are any collisions
    17341737    (it will return B_PERMISSION_DENIED in this case if \a wait is \c false).
    17351738
    1736     If \a session is -1, POSIX semantics are used for this lock. Otherwise,
     1739    If \a fd is -1, POSIX semantics are used for this lock. Otherwise,
    17371740    BSD flock() semantics are used, that is, all children can unlock the file
    17381741    in question (we even allow parents to remove the lock, though, but that
    17391742    seems to be in line to what the BSD's are doing).
    17401743*/
    17411744static status_t
    1742 acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock,
     1745acquire_advisory_lock(struct vnode* vnode, int fd, struct flock* flock,
    17431746    bool wait)
    17441747{
    17451748    FUNCTION(("acquire_advisory_lock(vnode = %p, flock = %p, wait = %s)\n",
    acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock,  
    17681771        while (iterator.HasNext()) {
    17691772            struct advisory_lock* lock = iterator.Next();
    17701773
    1771             // TODO: locks from the same team might be joinable!
    1772             if (lock->team != team && advisory_lock_intersects(lock, flock)) {
     1774            if ((lock->team != team || lock->fd != fd)
     1775                    && advisory_lock_intersects(lock, flock)) {
    17731776                // locks do overlap
    17741777                if (!shared || !lock->shared) {
    17751778                    // we need to wait
    acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock,  
    17861789
    17871790        if (!wait) {
    17881791            put_advisory_locking(locking);
    1789             return session != -1 ? B_WOULD_BLOCK : B_PERMISSION_DENIED;
     1792            return fd != -1 ? B_WOULD_BLOCK : B_PERMISSION_DENIED;
    17901793        }
    17911794
    17921795        status = switch_sem_etc(locking->lock, waitForLock, 1,
    acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock,  
    18081811    }
    18091812
    18101813    lock->team = team_get_current_team_id();
    1811     lock->session = session;
     1814    lock->session = thread_get_current_thread()->team->session_id;
     1815    lock->fd = fd;
    18121816    // values must already be normalized when getting here
    18131817    lock->start = flock->l_start;
    18141818    lock->end = flock->l_start - 1 + flock->l_len;
    file_close(struct file_descriptor* descriptor)  
    56265630        // remove all outstanding locks for this team
    56275631        if (HAS_FS_CALL(vnode, release_lock))
    56285632            status = FS_CALL(vnode, release_lock, descriptor->cookie, NULL);
    5629         else
    5630             status = release_advisory_lock(vnode, NULL);
     5633        else {
     5634            // FIXME should also release fd-pinned locks (how do we get the fd?)
     5635            // status = release_advisory_lock(vnode, fd, NULL);
     5636            status = release_advisory_lock(vnode, -1, NULL);
     5637        }
    56315638    }
    56325639    return status;
    56335640}
    common_fcntl(int fd, int op, size_t argument, bool kernel)  
    62106217                    status = FS_CALL(vnode, release_lock, descriptor->cookie,
    62116218                        &flock);
    62126219                } else
    6213                     status = release_advisory_lock(vnode, &flock);
     6220                    status = release_advisory_lock(vnode, -1, &flock);
    62146221            } else {
    62156222                // the open mode must match the lock type
    62166223                if (((descriptor->open_mode & O_RWMASK) == O_RDONLY
    _user_flock(int fd, int operation)  
    91109117
    91119118    status_t status;
    91129119    if ((operation & LOCK_UN) != 0)
    9113         status = release_advisory_lock(vnode, &flock);
     9120        status = release_advisory_lock(vnode, fd, &flock);
    91149121    else {
    9115         status = acquire_advisory_lock(vnode,
    9116             thread_get_current_thread()->team->session_id, &flock,
     9122        status = acquire_advisory_lock(vnode, fd, &flock,
    91179123            (operation & LOCK_NB) == 0);
    91189124    }
    91199125