shm_open2: Implement SHM_GROW_ON_WRITE
Lack of SHM_GROW_ON_WRITE is actively breaking Python's memfd_create tests, so go ahead and implement it. A future change will make memfd_create always set SHM_GROW_ON_WRITE, to match Linux behavior and unbreak Python's tests on -CURRENT. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D25502
This commit is contained in:
parent
2d68fac9bd
commit
3f07b9d9f8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=363065
@ -313,6 +313,7 @@ shm_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
|||||||
struct shmfd *shmfd;
|
struct shmfd *shmfd;
|
||||||
void *rl_cookie;
|
void *rl_cookie;
|
||||||
int error;
|
int error;
|
||||||
|
off_t size;
|
||||||
|
|
||||||
shmfd = fp->f_data;
|
shmfd = fp->f_data;
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
@ -321,17 +322,42 @@ shm_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
|||||||
return (error);
|
return (error);
|
||||||
#endif
|
#endif
|
||||||
foffset_lock_uio(fp, uio, flags);
|
foffset_lock_uio(fp, uio, flags);
|
||||||
|
if (uio->uio_resid > OFF_MAX - uio->uio_offset) {
|
||||||
|
/*
|
||||||
|
* Overflow is only an error if we're supposed to expand on
|
||||||
|
* write. Otherwise, we'll just truncate the write to the
|
||||||
|
* size of the file, which can only grow up to OFF_MAX.
|
||||||
|
*/
|
||||||
|
if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0) {
|
||||||
|
foffset_unlock_uio(fp, uio, flags);
|
||||||
|
return (EFBIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
size = shmfd->shm_size;
|
||||||
|
} else {
|
||||||
|
size = uio->uio_offset + uio->uio_resid;
|
||||||
|
}
|
||||||
if ((flags & FOF_OFFSET) == 0) {
|
if ((flags & FOF_OFFSET) == 0) {
|
||||||
rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX,
|
rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX,
|
||||||
&shmfd->shm_mtx);
|
&shmfd->shm_mtx);
|
||||||
} else {
|
} else {
|
||||||
rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset,
|
rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset,
|
||||||
uio->uio_offset + uio->uio_resid, &shmfd->shm_mtx);
|
size, &shmfd->shm_mtx);
|
||||||
}
|
}
|
||||||
if ((shmfd->shm_seals & F_SEAL_WRITE) != 0)
|
if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) {
|
||||||
error = EPERM;
|
error = EPERM;
|
||||||
else
|
} else {
|
||||||
error = uiomove_object(shmfd->shm_object, shmfd->shm_size, uio);
|
error = 0;
|
||||||
|
if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 &&
|
||||||
|
size > shmfd->shm_size) {
|
||||||
|
VM_OBJECT_WLOCK(shmfd->shm_object);
|
||||||
|
error = shm_dotruncate_locked(shmfd, size, rl_cookie);
|
||||||
|
VM_OBJECT_WUNLOCK(shmfd->shm_object);
|
||||||
|
}
|
||||||
|
if (error == 0)
|
||||||
|
error = uiomove_object(shmfd->shm_object,
|
||||||
|
shmfd->shm_size, uio);
|
||||||
|
}
|
||||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx);
|
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx);
|
||||||
foffset_unlock_uio(fp, uio, flags);
|
foffset_unlock_uio(fp, uio, flags);
|
||||||
return (error);
|
return (error);
|
||||||
@ -748,7 +774,7 @@ kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode,
|
|||||||
mode_t cmode;
|
mode_t cmode;
|
||||||
int error, fd, initial_seals;
|
int error, fd, initial_seals;
|
||||||
|
|
||||||
if ((shmflags & ~SHM_ALLOW_SEALING) != 0)
|
if ((shmflags & ~(SHM_ALLOW_SEALING | SHM_GROW_ON_WRITE)) != 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
initial_seals = F_SEAL_SEAL;
|
initial_seals = F_SEAL_SEAL;
|
||||||
@ -921,6 +947,7 @@ kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shmfd->shm_flags = shmflags;
|
||||||
finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
|
finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
|
||||||
|
|
||||||
td->td_retval[0] = fd;
|
td->td_retval[0] = fd;
|
||||||
|
@ -190,6 +190,7 @@
|
|||||||
* shmflags for shm_open2()
|
* shmflags for shm_open2()
|
||||||
*/
|
*/
|
||||||
#define SHM_ALLOW_SEALING 0x00000001
|
#define SHM_ALLOW_SEALING 0x00000001
|
||||||
|
#define SHM_GROW_ON_WRITE 0x00000002
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags for memfd_create().
|
* Flags for memfd_create().
|
||||||
@ -278,6 +279,7 @@ struct shmfd {
|
|||||||
struct rangelock shm_rl;
|
struct rangelock shm_rl;
|
||||||
struct mtx shm_mtx;
|
struct mtx shm_mtx;
|
||||||
|
|
||||||
|
int shm_flags;
|
||||||
int shm_seals;
|
int shm_seals;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user