Minor change to path lookup that fixes the bug that creating a file
[minix3.git] / servers / vfs / open.c
blob42a05622e5e9d211453ba6a5c83b413b1db41358
1 /* This file contains the procedures for creating, opening, closing, and
2 * seeking on files.
4 * The entry points into this file are
5 * do_creat: perform the CREAT system call
6 * do_open: perform the OPEN system call
7 * do_mknod: perform the MKNOD system call
8 * do_mkdir: perform the MKDIR system call
9 * do_close: perform the CLOSE system call
10 * do_lseek: perform the LSEEK system call
12 * Changes for VFS:
13 * Jul 2006 (Balazs Gerofi)
16 #include "fs.h"
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <minix/callnr.h>
22 #include <minix/com.h>
23 #include <minix/u64.h>
24 #include "file.h"
25 #include "fproc.h"
26 #include "lock.h"
27 #include "param.h"
28 #include <dirent.h>
29 #include <assert.h>
31 #include <minix/vfsif.h>
32 #include "vnode.h"
33 #include "vmnt.h"
35 #define offset_lo m2_l1
36 #define offset_high m2_l2
38 FORWARD _PROTOTYPE( int x_open, (int bits, int oflags, int omode,
39 char *lastc, struct vnode **vpp) );
40 FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) );
41 FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
43 /*===========================================================================*
44 * do_creat *
45 *===========================================================================*/
46 PUBLIC int do_creat()
48 /* Perform the creat(name, mode) system call. */
49 int r;
51 if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
52 r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
53 return(r);
56 /*===========================================================================*
57 * do_open *
58 *===========================================================================*/
59 PUBLIC int do_open()
61 /* Perform the open(name, flags,...) system call. */
62 int create_mode = 0; /* is really mode_t but this gives problems */
63 int r;
65 /* If O_CREAT is set, open has three parameters, otherwise two. */
66 if (m_in.mode & O_CREAT) {
67 create_mode = m_in.c_mode;
68 r = fetch_name(m_in.c_name, m_in.name1_length, M1);
69 } else {
70 r = fetch_name(m_in.name, m_in.name_length, M3);
73 if (r != OK) {
74 return(err_code); /* name was bad */
76 r = common_open(m_in.mode, create_mode);
77 return(r);
80 /*===========================================================================*
81 * common_open *
82 *===========================================================================*/
83 PRIVATE int common_open(register int oflags, mode_t omode)
85 /* Common code from do_creat and do_open. */
86 int r, b, found;
87 dev_t dev;
88 mode_t bits;
89 off_t pos;
90 struct dmap *dp;
91 struct filp *fil_ptr, *filp2;
92 struct vnode *vp, *vp2;
93 struct vmnt *vmp;
94 char Xlastc[NAME_MAX];
95 char *pathrem;
96 int m;
98 /* Request and response structures */
99 struct lookup_req Xlookup_req;
100 struct open_req Xreq;
102 /* Remap the bottom two bits of oflags. */
103 m = oflags & O_ACCMODE;
104 switch(m) {
105 case O_RDONLY: bits = R_BIT; break;
106 case O_WRONLY: bits = W_BIT; break;
107 case O_RDWR: bits = R_BIT | W_BIT; break;
108 default: return EINVAL;
111 /* See if file descriptor and filp slots are available. */
112 if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);
114 /* If O_CREATE, set umask */
115 if (oflags & O_CREAT) {
116 omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
119 vp= NULL;
121 /* Fill in lookup request fields */
122 Xlookup_req.path = user_fullpath;
123 Xlookup_req.lastc = Xlastc;
124 Xlookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR :
125 LAST_DIR_EATSYM) : EAT_PATH;
126 Xlookup_req.flags = ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) ?
127 LAST_DIR : EAT_PATH;
128 Xlastc[0]= '\0'; /* Clear lastc, it will be filled with the part of the
129 * path that cannot be resolved.
132 /* Request lookup */
133 r = Xlookup_vp(&Xlookup_req, &vp, &pathrem);
135 if (r == OK && ((oflags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL)))
137 /* Clear lastc */
138 Xlastc[0]= '\0';
141 /* Hide ENOENT for O_CREAT */
142 if (r == ENOENT && (oflags & O_CREAT))
144 if (pathrem == NULL)
145 panic(__FILE__, "no pathrem", NO_NUM);
147 /* If any path remains, but no '/', O_CREAT can continue.
148 * If no path remains, a null filename was provided so ENOENT
149 * remains.
151 if(*pathrem) {
152 if (strchr(pathrem, '/') == 0)
153 r= OK;
154 else
156 printf("common_open: / in pathrem\n");
161 if (r != OK)
163 if (vp)
165 put_vnode(vp);
166 vp= NULL;
168 return r;
171 if (!vp) panic(__FILE__, "common_open: no vp", NO_NUM);
173 r= x_open(bits, oflags, omode, Xlastc, &vp);
174 if (r != OK)
176 if (vp)
178 put_vnode(vp);
179 vp= NULL;
181 return r;
184 #if 0
185 /* Lookup was okay, fill in request fields for
186 * the actual open request. */
187 req.inode_nr = res.inode_nr;
188 req.fs_e = res.fs_e;
189 req.oflags = oflags;
190 req.omode = omode;
191 req.lastc = lastc;
192 req.uid = fp->fp_effuid;
193 req.gid = fp->fp_effgid;
195 /* Issue request */
196 if ((r = req_open(&req, &res)) != OK) return r;
198 /* Check whether the vnode is already in use */
199 if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
200 vp = vp2;
201 vp->v_size = res.fsize; /* In case of trunc... */
202 vp->v_ref_count++;
203 vp->v_fs_count++;
205 /* Otherwise use the free one */
206 else {
207 vp->v_fs_e = res.fs_e;
208 if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
209 printf("VFS: vmnt not found by open()");
211 vp->v_dev = vmp->m_dev;
212 vp->v_inode_nr = res.inode_nr;
213 vp->v_mode = res.fmode;
214 vp->v_uid = res.uid;
215 vp->v_gid = res.gid;
216 vp->v_size = res.fsize;
217 vp->v_sdev = res.dev;
218 vp->v_fs_count = 1;
219 vp->v_ref_count = 1;
220 vp->v_vmnt = vmp;
221 vp->v_index = res.inode_index;
223 #endif
225 /* Claim the file descriptor and filp slot and fill them in. */
226 fp->fp_filp[m_in.fd] = fil_ptr;
227 FD_SET(m_in.fd, &fp->fp_filp_inuse);
228 fil_ptr->filp_count = 1;
229 fil_ptr->filp_flags = oflags;
230 fil_ptr->filp_vno = vp;
232 vp->v_isfifo= FALSE;
233 switch (vp->v_mode & I_TYPE) {
234 case I_CHAR_SPECIAL:
235 /* Invoke the driver for special processing. */
236 r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE));
237 break;
239 case I_BLOCK_SPECIAL:
240 /* Invoke the driver for special processing. */
241 r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE));
242 #if 0
243 if (r != OK)
244 panic(__FILE__, "common_open: dev_open failed", r);
245 #endif
247 /* Check whether the device is mounted or not */
248 found = 0;
249 if (r == OK) {
250 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
251 if (vmp->m_dev == vp->v_sdev) {
252 found = 1;
253 break;
257 /* Who is going to be responsible for this device? */
258 if (found) {
259 vp->v_bfs_e = vmp->m_fs_e;
260 vp->v_blocksize - vmp->m_block_size;
262 else { /* To be handled in the root FS proc if not mounted */
263 vp->v_bfs_e = ROOT_FS_E;
264 vp->v_blocksize = _MIN_BLOCK_SIZE;
267 /* Get the driver endpoint of the block spec device */
268 dp = &dmap[(vp->v_sdev >> MAJOR) & BYTE];
269 if (dp->dmap_driver == NONE) {
270 printf("VFSblock_spec_open: driver not found for device %d\n",
271 vp->v_sdev);
272 r = EINVAL;
273 break;
276 /* Send the driver endpoint (even if it is known already...) */
277 if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver))
278 != OK) {
279 printf("VFSblock_spec_open: error sending driver endpoint\n");
282 break;
284 case I_NAMED_PIPE:
285 vp->v_pipe = I_PIPE;
286 vp->v_isfifo= TRUE;
287 oflags |= O_APPEND; /* force append mode */
288 fil_ptr->filp_flags = oflags;
289 r = pipe_open(vp, bits, oflags);
290 if (r != ENXIO) {
291 /* See if someone else is doing a rd or wt on
292 * the FIFO. If so, use its filp entry so the
293 * file position will be automatically shared.
295 b = (bits & R_BIT ? R_BIT : W_BIT);
296 assert(fil_ptr->filp_count == 1);
297 fil_ptr->filp_count = 0; /* don't find self */
298 if ((filp2 = find_filp(vp, b)) != NIL_FILP) {
299 /* Co-reader or writer found. Use it.*/
300 fp->fp_filp[m_in.fd] = filp2;
301 filp2->filp_count++;
302 filp2->filp_vno = vp;
303 filp2->filp_flags = oflags;
305 /* v_count was incremented after the vnode has
306 * been found, i_count was incremented incorrectly
307 * by eatpath in FS, not knowing that we were going to
308 * use an existing filp entry. Correct this error.
310 put_vnode(vp);
311 } else {
312 /* Nobody else found. Restore filp. */
313 fil_ptr->filp_count = 1;
314 if (fil_ptr->filp_mode == R_BIT)
315 fil_ptr->filp_pos = cvul64(vp->v_pipe_rd_pos);
316 else
317 fil_ptr->filp_pos = cvul64(vp->v_pipe_wr_pos);
320 break;
323 /* If error, release inode. */
324 if (r != OK) {
325 if (r == SUSPEND) return(r); /* Oops, just suspended */
326 fp->fp_filp[m_in.fd] = NIL_FILP;
327 FD_CLR(m_in.fd, &fp->fp_filp_inuse);
328 fil_ptr->filp_count= 0;
329 put_vnode(vp);
330 fil_ptr->filp_vno = NIL_VNODE;
331 return(r);
334 return(m_in.fd);
337 /*===========================================================================*
338 * x_open *
339 *===========================================================================*/
340 PRIVATE int x_open(bits, oflags, omode, lastc, vpp)
341 mode_t bits;
342 int oflags;
343 mode_t omode;
344 char *lastc;
345 struct vnode **vpp;
347 int r, b, exist = TRUE;
348 struct vnode *vp, *dvp, *tmp_vp;
349 struct vmnt *vmp;
350 struct node_details res;
352 /* If O_CREATE is set, try to make the file. */
353 if ((oflags & O_CREAT) && lastc[0] != '\0') {
354 dvp= *vpp; /* Parent directory */
356 /* See if a free vnode is available */
357 if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
358 printf("VFS x_open: no free vnode available\n");
359 return EINVAL;
362 r= req_create(dvp->v_fs_e, dvp->v_inode_nr, omode, fp->fp_effuid,
363 fp->fp_effgid, lastc, &res);
364 if (r != OK)
365 return r;
366 exist = FALSE;
368 /* Check whether vnode is already in use or not */
369 if ((tmp_vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
370 vp= tmp_vp;
371 vp->v_ref_count++;
372 vp->v_fs_count++;
374 else
376 /* Fill in the free vnode's fields */
377 vp->v_fs_e = res.fs_e;
378 vp->v_inode_nr = res.inode_nr;
379 vp->v_mode = res.fmode;
380 vp->v_size = res.fsize;
381 vp->v_uid = res.uid;
382 vp->v_gid = res.gid;
383 vp->v_sdev = res.dev;
385 if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
386 panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM);
388 vp->v_vmnt = vmp;
389 vp->v_dev = vmp->m_dev;
390 vp->v_fs_count = 1;
391 vp->v_ref_count = 1;
394 /* Release dvp */
395 put_vnode(dvp);
397 /* Update *vpp */
398 *vpp= vp;
400 else {
401 vp= *vpp;
404 /* Only do the normal open code if we didn't just create the file. */
405 if (!exist)
406 return OK;
408 /* Check protections. */
409 if ((r = forbidden(vp, bits)) != OK)
410 return r;
412 /* Opening reg. files directories and special files differ. */
413 switch (vp->v_mode & I_TYPE) {
414 case I_REGULAR:
415 /* Truncate regular file if O_TRUNC. */
416 if (oflags & O_TRUNC) {
417 if ((r = forbidden(vp, W_BIT)) !=OK) break;
418 truncate_vn(vp, 0);
420 break;
422 case I_DIRECTORY:
423 /* Directories may be read but not written. */
424 r = (bits & W_BIT ? EISDIR : OK);
425 break;
427 case I_CHAR_SPECIAL:
428 case I_BLOCK_SPECIAL:
429 if (vp->v_sdev == (dev_t)-1)
430 panic(__FILE__, "x_open: bad special", NO_NUM);
431 break;
433 case I_NAMED_PIPE:
434 if (vp->v_ref_count == 1)
436 if (vp->v_size != 0)
438 r= truncate_vn(vp, 0);
439 if (r != OK)
441 printf(
442 "x_open (fifo): truncate_vn failed: %d\n",
447 break;
450 return(r);
454 /*===========================================================================*
455 * pipe_open *
456 *===========================================================================*/
457 PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
458 register int oflags)
460 /* This function is called from common_open. It checks if
461 * there is at least one reader/writer pair for the pipe, if not
462 * it suspends the caller, otherwise it revives all other blocked
463 * processes hanging on the pipe.
466 vp->v_pipe = I_PIPE;
468 if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) {
469 printf("pipe opened RW.\n");
470 return ENXIO;
473 if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) {
474 if (oflags & O_NONBLOCK) {
475 if (bits & W_BIT) return(ENXIO);
476 } else {
477 suspend(XPOPEN); /* suspend caller */
478 return(SUSPEND);
480 } else if (susp_count > 0) {/* revive blocked processes */
481 release(vp, OPEN, susp_count);
482 release(vp, CREAT, susp_count);
484 return(OK);
490 /*===========================================================================*
491 * do_mknod *
492 *===========================================================================*/
493 PUBLIC int do_mknod()
495 /* Perform the mknod(name, mode, addr) system call. */
496 register mode_t bits, mode_bits;
497 char lastc[NAME_MAX]; /* last component of the path */
498 struct mknod_req req;
499 struct lookup_req lookup_req;
500 struct node_details res;
501 int r;
503 /* Only the super_user may make nodes other than fifos. */
504 mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */
505 if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
506 if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
507 bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
509 /* Fill in lookup request fields */
510 lookup_req.path = user_fullpath;
511 lookup_req.lastc = lastc;
512 lookup_req.flags = LAST_DIR;
514 /* Request lookup */
515 if ((r = lookup(&lookup_req, &res)) != OK) return r;
517 /* Lookup was okay, fill in request fields for the actual
518 * mknod request. */
519 req.fs_e = res.fs_e;
520 req.inode_nr = res.inode_nr;
521 req.rmode = bits;
522 req.dev = m_in.mk_z0;
523 req.lastc = lastc;
524 req.uid = fp->fp_effuid;
525 req.gid = fp->fp_effgid;
527 /* Issue request */
528 return req_mknod(&req);
532 /*===========================================================================*
533 * do_mkdir *
534 *===========================================================================*/
535 PUBLIC int do_mkdir()
537 /* Perform the mkdir(name, mode) system call. */
538 mode_t bits; /* mode bits for the new inode */
539 char lastc[NAME_MAX];
540 struct mkdir_req req;
541 struct lookup_req lookup_req;
542 struct node_details res;
543 int r;
545 /*printf("VFS: mkdir() START:");*/
546 if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
548 bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
550 /* Fill in lookup request fields */
551 lookup_req.path = user_fullpath;
552 lookup_req.lastc = lastc;
553 lookup_req.flags = LAST_DIR;
555 /* Request lookup */
556 if ((r = lookup(&lookup_req, &res)) != OK) return r;
558 /* Lookup was okay, fill in request message fields
559 * for the actual mknod request. */
560 req.fs_e = res.fs_e;
561 req.d_inode_nr = res.inode_nr;
562 req.rmode = bits;
563 req.lastc = lastc;
564 req.uid = fp->fp_effuid;
565 req.gid = fp->fp_effgid;
567 /* Issue request */
568 return req_mkdir(&req);
574 /*===========================================================================*
575 * do_lseek *
576 *===========================================================================*/
577 PUBLIC int do_lseek()
579 /* Perform the lseek(ls_fd, offset, whence) system call. */
580 register struct filp *rfilp;
581 int r;
582 long offset;
583 u64_t pos, newpos;
584 struct node_req req;
586 /* Check to see if the file descriptor is valid. */
587 if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
589 /* No lseek on pipes. */
590 if (rfilp->filp_vno->v_pipe == I_PIPE) return(ESPIPE);
592 /* The value of 'whence' determines the start position to use. */
593 switch(m_in.whence) {
594 case SEEK_SET: pos = cvu64(0); break;
595 case SEEK_CUR: pos = rfilp->filp_pos; break;
596 case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break;
597 default: return(EINVAL);
600 offset= m_in.offset_lo;
601 if (offset >= 0)
602 newpos= add64ul(pos, offset);
603 else
604 newpos= sub64ul(pos, -offset);
606 /* Check for overflow. */
607 if (ex64hi(newpos) != 0)
608 return EINVAL;
610 if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
611 /* Fill in request message */
612 req.fs_e = rfilp->filp_vno->v_fs_e;
613 req.inode_nr = rfilp->filp_vno->v_inode_nr;
615 /* Issue request */
616 if ((r = req_inhibread(&req)) != OK) return r;
619 rfilp->filp_pos = newpos;
621 /* insert the new position into the output message */
622 m_out.reply_l1 = ex64lo(newpos);
624 return(OK);
628 /*===========================================================================*
629 * do_llseek *
630 *===========================================================================*/
631 PUBLIC int do_llseek()
633 /* Perform the llseek(ls_fd, offset, whence) system call. */
634 register struct filp *rfilp;
635 u64_t pos, newpos;
636 struct node_req req;
637 int r;
639 /* Check to see if the file descriptor is valid. */
640 if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
642 /* No lseek on pipes. */
643 if (rfilp->filp_vno->v_pipe == I_PIPE) return(ESPIPE);
645 /* The value of 'whence' determines the start position to use. */
646 switch(m_in.whence) {
647 case SEEK_SET: pos = cvu64(0); break;
648 case SEEK_CUR: pos = rfilp->filp_pos; break;
649 case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break;
650 default: return(EINVAL);
653 newpos= add64(pos, make64(m_in.offset_lo, m_in.offset_high));
655 /* Check for overflow. */
656 if (((long)m_in.offset_high > 0) && cmp64(newpos, pos) < 0)
657 return(EINVAL);
658 if (((long)m_in.offset_high < 0) && cmp64(newpos, pos) > 0)
659 return(EINVAL);
661 if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
662 /* Fill in request message */
663 req.fs_e = rfilp->filp_vno->v_fs_e;
664 req.inode_nr = rfilp->filp_vno->v_inode_nr;
666 /* Issue request */
667 if ((r = req_inhibread(&req)) != OK) return r;
670 rfilp->filp_pos = newpos;
671 m_out.reply_l1 = ex64lo(newpos);
672 m_out.reply_l2 = ex64hi(newpos);
673 return(OK);
677 /*===========================================================================*
678 * do_close *
679 *===========================================================================*/
680 PUBLIC int do_close()
682 /* Perform the close(fd) system call. */
683 return close_fd(fp, m_in.fd);
687 /*===========================================================================*
688 * close_fd *
689 *===========================================================================*/
690 PUBLIC int close_fd(rfp, fd_nr)
691 struct fproc *rfp;
692 int fd_nr;
694 /* Perform the close(fd) system call. */
695 register struct filp *rfilp;
696 register struct vnode *vp;
697 struct file_lock *flp;
698 int rw, mode_word, lock_count;
699 dev_t dev;
701 /* First locate the vnode that belongs to the file descriptor. */
702 if ( (rfilp = get_filp2(rfp, fd_nr)) == NIL_FILP) return(err_code);
704 vp = rfilp->filp_vno;
706 if (rfilp->filp_count - 1 == 0 && rfilp->filp_mode != FILP_CLOSED) {
707 /* Check to see if the file is special. */
708 mode_word = vp->v_mode & I_TYPE;
709 if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
710 dev = (dev_t) vp->v_sdev;
711 if (mode_word == I_BLOCK_SPECIAL) {
712 if (vp->v_bfs_e == ROOT_FS_E)
714 /* Invalidate the cache unless the special is
715 * mounted. Assume that the root filesystem's
716 * is open only for fsck.
718 req_flush(vp->v_bfs_e, dev);
721 /* Do any special processing on device close. */
722 dev_close(dev);
726 /* If the inode being closed is a pipe, release everyone hanging on it. */
727 if (vp->v_pipe == I_PIPE) {
728 rw = (rfilp->filp_mode & R_BIT ? WRITE : READ);
729 release(vp, rw, NR_PROCS);
732 /* If a write has been done, the inode is already marked as DIRTY. */
733 if (--rfilp->filp_count == 0) {
734 if (vp->v_pipe == I_PIPE) {
735 /* Last reader or writer is going. Tell MFS about latest
736 * pipe size.
738 truncate_vn(vp, vp->v_size);
740 if (vp->v_pipe == I_PIPE && vp->v_ref_count > 1) {
741 /* Save the file position in the v-node in case needed later.
742 * The read and write positions are saved separately.
744 if (rfilp->filp_mode == R_BIT)
745 vp->v_pipe_rd_pos = ex64lo(rfilp->filp_pos);
746 else
747 vp->v_pipe_wr_pos = ex64lo(rfilp->filp_pos);
750 else {
751 /* Otherwise zero the pipe position fields */
752 vp->v_pipe_rd_pos = 0;
753 vp->v_pipe_wr_pos = 0;
756 put_vnode(rfilp->filp_vno);
759 FD_CLR(fd_nr, &rfp->fp_cloexec_set);
760 rfp->fp_filp[fd_nr] = NIL_FILP;
761 FD_CLR(fd_nr, &rfp->fp_filp_inuse);
763 /* Check to see if the file is locked. If so, release all locks. */
764 if (nr_locks == 0) return(OK);
765 lock_count = nr_locks; /* save count of locks */
766 for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
767 if (flp->lock_type == 0) continue; /* slot not in use */
768 if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) {
769 flp->lock_type = 0;
770 nr_locks--;
773 if (nr_locks < lock_count) lock_revive(); /* lock released */
774 return(OK);