*
* MPSAFE
*/
-struct filedesc *
-fdcopy(struct proc *p)
+int
+fdcopy(struct proc *p, struct filedesc **fpp)
{
struct filedesc *fdp = p->p_fd;
struct filedesc *newfdp;
* Certain daemons might not have file descriptors.
*/
if (fdp == NULL)
- return (NULL);
+ return (0);
/*
* Allocate the new filedesc and fd_files[] array. This can race
* with operations by other threads on the fdp so we have to be
* careful.
*/
- newfdp = kmalloc(sizeof(struct filedesc), M_FILEDESC, M_WAITOK | M_ZERO);
+ newfdp = kmalloc(sizeof(struct filedesc),
+ M_FILEDESC, M_WAITOK | M_ZERO | M_NULLOK);
+ if (newfdp == NULL) {
+ *fpp = NULL;
+ return (-1);
+ }
again:
spin_lock(&fdp->fd_spin);
if (fdp->fd_lastfile < NDFILE) {
}
}
spin_unlock(&fdp->fd_spin);
- return (newfdp);
+ *fpp = newfdp;
+ return (0);
}
/*
if (p->p_fd->fd_refcnt > 1) {
struct filedesc *tmp;
- tmp = fdcopy(p);
+ error = fdcopy(p, &tmp);
+ if (error != 0)
+ goto exec_fail;
fdfree(p, tmp);
}
if (flags & RFFDG) {
if (p1->p_fd->fd_refcnt > 1) {
struct filedesc *newfd;
- newfd = fdcopy(p1);
+ error = fdcopy(p1, &newfd);
+ if (error != 0) {
+ error = ENOMEM;
+ goto done;
+ }
fdfree(p1, newfd);
}
}
p2->p_fd = fdinit(p1);
fdtol = NULL;
} else if (flags & RFFDG) {
- p2->p_fd = fdcopy(p1);
+ error = fdcopy(p1, &p2->p_fd);
+ if (error != 0) {
+ error = ENOMEM;
+ goto done;
+ }
fdtol = NULL;
} else {
p2->p_fd = fdshare(p1);
void fdinit_bootstrap(struct proc *p0, struct filedesc *fdp0, int cmask);
struct filedesc *fdinit (struct proc *p);
struct filedesc *fdshare (struct proc *p);
-struct filedesc *fdcopy (struct proc *p);
+int fdcopy (struct proc *p, struct filedesc **fpp);
void fdfree (struct proc *p, struct filedesc *repl);
int fdrevoke(void *f_data, short f_type, struct ucred *cred);
int closef (struct file *fp, struct proc *p);