📄 gfs_descrip.c
字号:
/* set syncronous write if regular file */ if ((gp->g_mode&GFMT) != GFREG) { if ((gp->g_mode&GFMT) == GFSOCK) { /* * 004 - If a socket was given, return * appropriate error. */ u.u_error = EOPNOTSUPP; } else { /* * 004 - Not a regular file or socket. Return * appropriate error. */ u.u_error = EINVAL; } break; } /* * Its a regular file, now check fp flag to * verify that file is open for writing. If not, return * an error. */ if ((fp->f_flag&FWRITE) == 0) { u.u_error = EINVAL; } else { fp->f_flag |= FSYNCRON; } break; case F_CLRSYN: /* Clear syncronous write flag */ /* First verify it is a regular file. */ if ((gp->g_mode&GFMT) != GFREG) { if ((gp->g_mode&GFMT) == GFSOCK) { /* * If a socket was given, return * appropriate error. */ u.u_error = EOPNOTSUPP; } else { /* * Not a regular file or socket. Return * appropriate error. */ u.u_error = EINVAL; } break; } /* Regular file ! */ fp->f_flag &= ~FSYNCRON; break; default: u.u_error = EINVAL; } smp_unlock(&fp->f_lk);}fset(fp, bit, value) register struct file *fp; register int bit; int value;{ if (value) fp->f_flag |= bit; else fp->f_flag &= ~bit; return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), (caddr_t)&value));}fgetown(fp, valuep) register struct file *fp; register int *valuep;{ register int error; switch (fp->f_type) { case DTYPE_SOCKET: *valuep = ((struct socket *)fp->f_data)->so_pgrp; /*001*/ return (0); case DTYPE_PIPE: case DTYPE_PORT: error = fioctl(fp, (int)FIOGETOWN, (caddr_t)valuep); return (error); default: error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); *valuep = -*valuep; return (error); }}fsetown(fp, value) register struct file *fp; int value;{ if (fp->f_type == DTYPE_SOCKET) { ((struct socket *)fp->f_data)->so_pgrp = value; /*001*/ return (0); } if ((fp->f_type == DTYPE_PIPE) || (fp->f_type == DTYPE_PORT)) return (fioctl(fp, (int)FIOSETOWN, (caddr_t)&value)); if (value > 0) { struct proc *p = pfind(value); if (p == 0) return (EINVAL); value = p->p_pgrp; } else value = -value; return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));}fioctl(fp, cmd, value) register struct file *fp; register int cmd; register caddr_t value;{ return ((*fp->f_ops->fo_ioctl)(fp, cmd, value, u.u_cred));}close(){ register struct a { int i; } *uap = (struct a *)u.u_ap; register struct file *fp; register struct gnode *gp; register int j; register caddr_t value; GETF(fp, uap->i); /* Release all System-V style record locks, if any */ (void) gno_lockrelease (fp); /* error? */ gp = (struct gnode *)fp->f_data; if ((U_POFILE(uap->i) & UF_INUSE) && gp) { U_POFILE_SET(uap->i, U_POFILE(uap->i) & ~UF_INUSE); /* clear inuse only when last inuse open file */ for (j=0; j <= u.u_omax; j++) if ((U_POFILE(j) & UF_INUSE) && U_OFILE(j) == fp) goto stillinuse; (*fp->f_ops->fo_ioctl)(fp, FIOCINUSE, value, u.u_cred); gfs_lock(gp); gp->g_flag &= ~(GINUSE); gfs_unlock(gp); wakeup((caddr_t)&gp->g_flag); }stillinuse: U_OFILE_SET(uap->i, NULL); U_POFILE_SET(uap->i, 0); /* audit info */ if ( audswitch && gp ) { u.u_gno_dev[0] = (gp->g_mode&GFMT) == GFCHR ? gp->g_rdev : gp->g_dev; u.u_gno_num[0] = gp->g_number; u.u_gno_indx = 1; } u.u_error = closef(fp); AUDIT_CALL ( u.u_event, u.u_error, u.u_r.r_val1, AUD_HDR|AUD_PRM|AUD_RES, (int *)0, 0 ); /* * It's a no-op, why call it? * * if (*pf & UF_MAPPED) * munmapfd(uap->i); */ } fstat(){ register struct file *fp; register struct a { int fdes; struct stat *sb; } *uap; struct stat ub; uap = (struct a *)u.u_ap; GETF(fp, uap->fdes); switch (fp->f_type) { case DTYPE_PORT: case DTYPE_INODE: case DTYPE_PIPE: if (fp->f_data) u.u_error = gno_stat((struct gnode *)fp->f_data, &ub); else u.u_error = EBADF; break; case DTYPE_SOCKET: u.u_error = soo_stat((struct socket *)fp->f_data, &ub); break; default: panic("fstat"); /*NOTREACHED*/ } if (u.u_error == 0) u.u_error = copyout((caddr_t)&ub,(caddr_t)uap->sb,sizeof (ub));}/* * Allocate descriptor slots in the range [0 .. max_nofile], assuming that * the range [0 .. NOFILE_IN_U] is currently allocated. Intended to be * called only from the enable_fd_slots macro. * * Return 0 on success, -1 on failure. */intalloc_fd_slots(fdno) int fdno; /* fd of interest */{ struct file **ofilep; char *pofilep; int count; /* * The first overflow buffer will contain 64 file descriptors. * Subsequent allocations will double buffer size. */ if (u.u_of_count == 0) count = NOFILE_IN_U; else count = 2 * u.u_of_count; /* * If the buffer size calculated above is not big enough to be * able to reference the fd of interest, we figure out how big * the buffer needs to be (making it a multiple of NOFILE_IN_U). * This case can happen as a result of a dup2. */ if (fdno >= (count + NOFILE_IN_U)) count = (fdno / NOFILE_IN_U) * NOFILE_IN_U; /* * Allocate new overflow structures. KM_ALLOC may sleep * waiting to allocate virtual memory, but will never * fail. */ KM_ALLOC(ofilep, struct file **, count * sizeof (struct file *), KM_NOFILE, KM_CLEAR); KM_ALLOC(pofilep, char *, count, KM_NOFILE, KM_CLEAR); /* * Copy current overflow buffer if it exists. */ if (u.u_of_count) { bcopy(u.u_ofile_of, ofilep, u.u_of_count * sizeof (struct file *)); bcopy(u.u_pofile_of, pofilep, u.u_of_count); /* * Release previous memory back to pool. */ KM_FREE(u.u_ofile_of, KM_NOFILE); KM_FREE(u.u_pofile_of, KM_NOFILE); } /* * Update pointers and current counts. */ u.u_ofile_of = ofilep; u.u_pofile_of = pofilep; u.u_of_count = count; return(u.u_error);}/* * Allocate a user file descriptor. */ufalloc(i) register int i;{ for (; i < max_nofile; i++) { /* * Make sure that slot i exists before referring to it. */ if (enable_fd_slot(i)) return (-1); if (U_OFILE(i) == NULL) { u.u_r.r_val1 = i; U_POFILE_SET(i, 0); if (i > u.u_omax) u.u_omax = i; return (i); } } u.u_error = EMFILE; return (-1);}ufavail(){ register int i; register int maxfd; register int avail; /* * If the process hasn't yet had occasion to allocate its * overflow descriptor array out to the maximum extent, confine the * search to the preallocated slots and credit the descriptors * obtainable by reallocating to the maximum extent. */ if (u.u_omax >= 0) maxfd = u.u_omax; else return(max_nofile); avail = (max_nofile - maxfd) - 1; for (i = 0; i < maxfd; i++) if (U_OFILE(i) == NULL) avail++; return (avail);}struct file *lastf;/* * Allocate a user file descriptor * and a file structure. * Initialize the descriptor * to point at the file structure. */struct file *falloc(){ register struct file *fp; register int i; i = ufalloc(0); if (i < 0) return (NULL); smp_lock(&lk_file, LK_RETRY); if (lastf == 0) lastf = file; for (fp = lastf; fp < fileNFILE; fp++) if (fp->f_count == 0) goto slot; for (fp = file; fp < lastf; fp++) if (fp->f_count == 0) goto slot; smp_unlock(&lk_file); tablefull("file"); u.u_error = ENFILE; return (NULL);slot: fp->f_data = 0; fp->f_count = 1; lastf = fp + 1; smp_unlock(&lk_file); U_OFILE_SET(i, fp); fp->f_offset = 0; crhold(u.u_cred); fp->f_cred = u.u_cred; return (fp);}/* * Convert a user supplied file descriptor into a pointer * to a file structure. Only task is to check range of the descriptor. * Critical paths should use the GETF macro. */struct file *getf(f) register int f;{ register struct file *fp; if (f < 0 || (unsigned)f > u.u_omax || (fp = U_OFILE(f)) == NULL) { u.u_error = EBADF; return (NULL); } return (fp);}/* * Internal form of close. * Decrement reference count on file structure. */int closef_nulls = 0;int gc_count = 0;closef(fp) register struct file *fp;{ register int othernbuf = 0; int err; if (fp == NULL) { closef_nulls++; return(0); } smp_lock(&fp->f_lk, LK_RETRY); cleanlocks(fp); /* 002 */ if(fp->f_flag&FNBUF) { struct gnode *gp = (struct gnode *)fp->f_data; othernbuf = asyncclose(gp->g_rdev, fp->f_flag); } smp_lock(&lk_file, LK_RETRY); if (fp->f_count > 1) { fp->f_count--; smp_unlock(&lk_file); if (fp->f_count == fp->f_msgcount) gc_count += fp->f_msgcount; smp_unlock(&fp->f_lk); return(0); } smp_unlock(&lk_file); if(fp->f_flag&FNBUF) { struct gnode *gp = (struct gnode *)fp->f_data; fp->f_flag &= ~FNBUF; if(!othernbuf) { gfs_lock(gp); gp->g_flag &= ~GSYNC; gfs_unlock(gp); } } err = (*fp->f_ops->fo_close)(fp); crfree(fp->f_cred); smp_lock(&lk_file, LK_RETRY); fp->f_data = (caddr_t)0; fp->f_count = 0; smp_unlock(&lk_file); smp_unlock(&fp->f_lk); return(err);}/* * Apply an advisory lock on a file descriptor. */flock(){ register struct a { int fd; int how; } *uap = (struct a *)u.u_ap; register struct file *fp; GETF(fp, uap->fd); if (fp->f_type != DTYPE_INODE && fp->f_type != DTYPE_PORT ) { u.u_error = EOPNOTSUPP; return; } if ((uap->how & (LOCK_UN|LOCK_EX|LOCK_SH)) == 0){ u.u_error = EINVAL; return; } if (uap->how & LOCK_UN) { smp_lock(&fp->f_lk, LK_RETRY); gno_unlock(fp, FSHLOCK|FEXLOCK); smp_unlock(&fp->f_lk); return; } /* SMP lock file table entry while locking file descriptor */ smp_lock(&fp->f_lk, LK_RETRY); /* avoid work... */ if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) { smp_unlock(&fp->f_lk); return; } if (fp->f_data) u.u_error = gno_lock(fp, uap->how); else u.u_error = EBADF; smp_unlock(&fp->f_lk);}/* * Normalize System V-style record locks */rewhence(ld, fp, newwhence) struct flock *ld; struct file *fp; int newwhence;{ register int error; struct gnode *gp = (struct gnode *)fp->f_data; /* * If reference is to end-of-file, then get current attributes. * Three return values are possible: unimplemented (GNOFUNC), * error (u.u_error), and normal return (0). */ if ((ld->l_whence == 2) || (newwhence == 2)) { if ((error = GGETVAL(gp)) > 0 ) { return (error); } } /* normalize to start of file */ switch (ld->l_whence) { case 0: break; case 1: ld->l_start += fp->f_offset; break; case 2: ld->l_start += gp->g_size; break; default: return(EINVAL); } /* renormalize to given start point */ switch (ld->l_whence = newwhence) { case 0: break; case 1: ld->l_start -= fp->f_offset; break; case 2: ld->l_start -= gp->g_size; break; default: return (EINVAL); } return(0);}/* * Initialize the file table locks. */finit(){ struct file *fp; extern struct lk_acct lk_acct; lockinit(&lk_file, &lock_file_d); lockinit(&lk_acct, &lock_acct_d); for (fp = file; fp < fileNFILE; fp++) { lockinit(&fp->f_lk, &lock_eachfile_d); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -