1 /* 2 * Copyright (c) 1990, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95 34 * $FreeBSD: src/sys/miscfs/fifofs/fifo_vnops.c,v 1.45.2.4 2003/04/22 10:11:24 bde Exp $ 35 * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.30 2006/06/13 08:12:04 dillon Exp $ 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/unistd.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/malloc.h> 44 #include <sys/thread2.h> 45 #include <sys/vnode.h> 46 #include <sys/socket.h> 47 #include <sys/socketvar.h> 48 #include <sys/filio.h> 49 #include <sys/fcntl.h> 50 #include <sys/file.h> 51 #include <sys/event.h> 52 #include <sys/poll.h> 53 #include <sys/un.h> 54 55 #include <sys/thread2.h> 56 57 #include "fifo.h" 58 59 /* 60 * This structure is associated with the FIFO vnode and stores 61 * the state associated with the FIFO. 62 */ 63 struct fifoinfo { 64 struct socket *fi_readsock; 65 struct socket *fi_writesock; 66 long fi_readers; 67 long fi_writers; 68 }; 69 70 static int fifo_badop (void); 71 static int fifo_print (struct vop_print_args *); 72 static int fifo_lookup (struct vop_old_lookup_args *); 73 static int fifo_open (struct vop_open_args *); 74 static int fifo_close (struct vop_close_args *); 75 static int fifo_read (struct vop_read_args *); 76 static int fifo_write (struct vop_write_args *); 77 static int fifo_ioctl (struct vop_ioctl_args *); 78 static int fifo_poll (struct vop_poll_args *); 79 static int fifo_kqfilter (struct vop_kqfilter_args *); 80 static int fifo_inactive (struct vop_inactive_args *); 81 static int fifo_bmap (struct vop_bmap_args *); 82 static int fifo_pathconf (struct vop_pathconf_args *); 83 static int fifo_advlock (struct vop_advlock_args *); 84 85 static void filt_fifordetach(struct knote *kn); 86 static int filt_fiforead(struct knote *kn, long hint); 87 static void filt_fifowdetach(struct knote *kn); 88 static int filt_fifowrite(struct knote *kn, long hint); 89 90 static struct filterops fiforead_filtops = 91 { 1, NULL, filt_fifordetach, filt_fiforead }; 92 static struct filterops fifowrite_filtops = 93 { 1, NULL, filt_fifowdetach, filt_fifowrite }; 94 95 struct vop_ops *fifo_vnode_vops; 96 static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { 97 { &vop_default_desc, (vnodeopv_entry_t) vop_defaultop }, 98 { &vop_access_desc, (vnodeopv_entry_t) vop_ebadf }, 99 { &vop_advlock_desc, (vnodeopv_entry_t) fifo_advlock }, 100 { &vop_bmap_desc, (vnodeopv_entry_t) fifo_bmap }, 101 { &vop_close_desc, (vnodeopv_entry_t) fifo_close }, 102 { &vop_old_create_desc, (vnodeopv_entry_t) fifo_badop }, 103 { &vop_getattr_desc, (vnodeopv_entry_t) vop_ebadf }, 104 { &vop_inactive_desc, (vnodeopv_entry_t) fifo_inactive }, 105 { &vop_ioctl_desc, (vnodeopv_entry_t) fifo_ioctl }, 106 { &vop_kqfilter_desc, (vnodeopv_entry_t) fifo_kqfilter }, 107 { &vop_old_link_desc, (vnodeopv_entry_t) fifo_badop }, 108 { &vop_old_lookup_desc, (vnodeopv_entry_t) fifo_lookup }, 109 { &vop_old_mkdir_desc, (vnodeopv_entry_t) fifo_badop }, 110 { &vop_old_mknod_desc, (vnodeopv_entry_t) fifo_badop }, 111 { &vop_open_desc, (vnodeopv_entry_t) fifo_open }, 112 { &vop_pathconf_desc, (vnodeopv_entry_t) fifo_pathconf }, 113 { &vop_poll_desc, (vnodeopv_entry_t) fifo_poll }, 114 { &vop_print_desc, (vnodeopv_entry_t) fifo_print }, 115 { &vop_read_desc, (vnodeopv_entry_t) fifo_read }, 116 { &vop_readdir_desc, (vnodeopv_entry_t) fifo_badop }, 117 { &vop_readlink_desc, (vnodeopv_entry_t) fifo_badop }, 118 { &vop_reallocblks_desc, (vnodeopv_entry_t) fifo_badop }, 119 { &vop_reclaim_desc, (vnodeopv_entry_t) vop_null }, 120 { &vop_old_remove_desc, (vnodeopv_entry_t) fifo_badop }, 121 { &vop_old_rename_desc, (vnodeopv_entry_t) fifo_badop }, 122 { &vop_old_rmdir_desc, (vnodeopv_entry_t) fifo_badop }, 123 { &vop_setattr_desc, (vnodeopv_entry_t) vop_ebadf }, 124 { &vop_old_symlink_desc, (vnodeopv_entry_t) fifo_badop }, 125 { &vop_write_desc, (vnodeopv_entry_t) fifo_write }, 126 { NULL, NULL } 127 }; 128 static struct vnodeopv_desc fifo_vnodeop_opv_desc = 129 { &fifo_vnode_vops, fifo_vnodeop_entries, 0 }; 130 131 VNODEOP_SET(fifo_vnodeop_opv_desc); 132 133 static MALLOC_DEFINE(M_FIFOINFO, "Fifo info", "Fifo info entries"); 134 135 /* 136 * fifo_vnoperate(struct vnodeop_desc *a_desc, ...) 137 */ 138 int 139 fifo_vnoperate(struct vop_generic_args *ap) 140 { 141 return (VOCALL(fifo_vnode_vops, ap)); 142 } 143 144 /* 145 * Trivial lookup routine that always fails. 146 * 147 * fifo_lookup(struct vnode *a_dvp, struct vnode **a_vpp, 148 * struct componentname *a_cnp) 149 */ 150 /* ARGSUSED */ 151 static int 152 fifo_lookup(struct vop_old_lookup_args *ap) 153 { 154 *ap->a_vpp = NULL; 155 return (ENOTDIR); 156 } 157 158 /* 159 * Open called to set up a new instance of a fifo or 160 * to find an active instance of a fifo. 161 * 162 * fifo_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred, 163 * struct thread *a_td) 164 */ 165 /* ARGSUSED */ 166 static int 167 fifo_open(struct vop_open_args *ap) 168 { 169 struct thread *td = curthread; 170 struct vnode *vp = ap->a_vp; 171 struct fifoinfo *fip; 172 struct socket *rso, *wso; 173 int error; 174 175 if ((fip = vp->v_fifoinfo) == NULL) { 176 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_FIFOINFO, M_WAITOK); 177 vp->v_fifoinfo = fip; 178 error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, td); 179 if (error) { 180 free(fip, M_FIFOINFO); 181 vp->v_fifoinfo = NULL; 182 return (error); 183 } 184 fip->fi_readsock = rso; 185 error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, td); 186 if (error) { 187 soclose(rso, FNONBLOCK); 188 free(fip, M_FIFOINFO); 189 vp->v_fifoinfo = NULL; 190 return (error); 191 } 192 fip->fi_writesock = wso; 193 error = unp_connect2(wso, rso); 194 if (error) { 195 soclose(wso, FNONBLOCK); 196 soclose(rso, FNONBLOCK); 197 free(fip, M_FIFOINFO); 198 vp->v_fifoinfo = NULL; 199 return (error); 200 } 201 fip->fi_readers = fip->fi_writers = 0; 202 wso->so_snd.sb_lowat = PIPE_BUF; 203 rso->so_state |= SS_CANTRCVMORE; 204 } 205 if (ap->a_mode & FREAD) { 206 fip->fi_readers++; 207 if (fip->fi_readers == 1) { 208 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 209 if (fip->fi_writers > 0) { 210 wakeup((caddr_t)&fip->fi_writers); 211 sowwakeup(fip->fi_writesock); 212 } 213 } 214 } 215 if (ap->a_mode & FWRITE) { 216 fip->fi_writers++; 217 if (fip->fi_writers == 1) { 218 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 219 if (fip->fi_readers > 0) { 220 wakeup((caddr_t)&fip->fi_readers); 221 sorwakeup(fip->fi_writesock); 222 } 223 } 224 } 225 if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) { 226 if (fip->fi_writers == 0) { 227 VOP_UNLOCK(vp, 0); 228 error = tsleep((caddr_t)&fip->fi_readers, 229 PCATCH, "fifoor", 0); 230 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 231 if (error) 232 goto bad; 233 /* 234 * We must have got woken up because we had a writer. 235 * That (and not still having one) is the condition 236 * that we must wait for. 237 */ 238 } 239 } 240 if (ap->a_mode & FWRITE) { 241 if (ap->a_mode & O_NONBLOCK) { 242 if (fip->fi_readers == 0) { 243 error = ENXIO; 244 goto bad; 245 } 246 } else { 247 if (fip->fi_readers == 0) { 248 VOP_UNLOCK(vp, 0); 249 error = tsleep((caddr_t)&fip->fi_writers, 250 PCATCH, "fifoow", 0); 251 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 252 if (error) 253 goto bad; 254 /* 255 * We must have got woken up because we had 256 * a reader. That (and not still having one) 257 * is the condition that we must wait for. 258 */ 259 } 260 } 261 } 262 return (vop_stdopen(ap)); 263 bad: 264 vop_stdopen(ap); /* bump opencount/writecount as appropriate */ 265 VOP_CLOSE(vp, ap->a_mode); 266 return (error); 267 } 268 269 /* 270 * Vnode op for read 271 * 272 * fifo_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag, 273 * struct ucred *a_cred) 274 */ 275 /* ARGSUSED */ 276 static int 277 fifo_read(struct vop_read_args *ap) 278 { 279 struct uio *uio = ap->a_uio; 280 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 281 int error, startresid; 282 int flags; 283 284 #ifdef DIAGNOSTIC 285 if (uio->uio_rw != UIO_READ) 286 panic("fifo_read mode"); 287 #endif 288 if (uio->uio_resid == 0) 289 return (0); 290 if (ap->a_ioflag & IO_NDELAY) 291 flags = MSG_FNONBLOCKING; 292 else 293 flags = 0; 294 startresid = uio->uio_resid; 295 VOP_UNLOCK(ap->a_vp, 0); 296 error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0, 297 (struct mbuf **)0, &flags); 298 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 299 return (error); 300 } 301 302 /* 303 * Vnode op for write 304 * 305 * fifo_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag, 306 * struct ucred *a_cred) 307 */ 308 /* ARGSUSED */ 309 static int 310 fifo_write(struct vop_write_args *ap) 311 { 312 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 313 struct thread *td = ap->a_uio->uio_td; 314 int error; 315 int flags; 316 317 #ifdef DIAGNOSTIC 318 if (ap->a_uio->uio_rw != UIO_WRITE) 319 panic("fifo_write mode"); 320 #endif 321 if (ap->a_ioflag & IO_NDELAY) 322 flags = MSG_FNONBLOCKING; 323 else 324 flags = 0; 325 VOP_UNLOCK(ap->a_vp, 0); 326 error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0, 327 (struct mbuf *)0, flags, td); 328 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 329 return (error); 330 } 331 332 /* 333 * Device ioctl operation. 334 * 335 * fifo_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data, int a_fflag, 336 * struct ucred *a_cred, struct thread *a_td) 337 */ 338 /* ARGSUSED */ 339 static int 340 fifo_ioctl(struct vop_ioctl_args *ap) 341 { 342 struct file filetmp; /* Local */ 343 int error; 344 345 if (ap->a_fflag & FREAD) { 346 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 347 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_cred); 348 if (error) 349 return (error); 350 } 351 if (ap->a_fflag & FWRITE) { 352 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 353 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_cred); 354 if (error) 355 return (error); 356 } 357 return (0); 358 } 359 360 /* 361 * fifo_kqfilter(struct vnode *a_vp, struct knote *a_kn) 362 */ 363 /* ARGSUSED */ 364 static int 365 fifo_kqfilter(struct vop_kqfilter_args *ap) 366 { 367 struct fifoinfo *fi = ap->a_vp->v_fifoinfo; 368 struct socket *so; 369 struct sockbuf *sb; 370 371 switch (ap->a_kn->kn_filter) { 372 case EVFILT_READ: 373 ap->a_kn->kn_fop = &fiforead_filtops; 374 so = fi->fi_readsock; 375 sb = &so->so_rcv; 376 break; 377 case EVFILT_WRITE: 378 ap->a_kn->kn_fop = &fifowrite_filtops; 379 so = fi->fi_writesock; 380 sb = &so->so_snd; 381 break; 382 default: 383 return (1); 384 } 385 386 ap->a_kn->kn_hook = (caddr_t)so; 387 388 SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext); 389 sb->sb_flags |= SB_KNOTE; 390 391 return (0); 392 } 393 394 static void 395 filt_fifordetach(struct knote *kn) 396 { 397 struct socket *so = (struct socket *)kn->kn_hook; 398 399 SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext); 400 if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note)) 401 so->so_rcv.sb_flags &= ~SB_KNOTE; 402 } 403 404 static int 405 filt_fiforead(struct knote *kn, long hint) 406 { 407 struct socket *so = (struct socket *)kn->kn_hook; 408 409 kn->kn_data = so->so_rcv.sb_cc; 410 if (so->so_state & SS_CANTRCVMORE) { 411 kn->kn_flags |= EV_EOF; 412 return (1); 413 } 414 kn->kn_flags &= ~EV_EOF; 415 return (kn->kn_data > 0); 416 } 417 418 static void 419 filt_fifowdetach(struct knote *kn) 420 { 421 struct socket *so = (struct socket *)kn->kn_hook; 422 423 SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext); 424 if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note)) 425 so->so_snd.sb_flags &= ~SB_KNOTE; 426 } 427 428 static int 429 filt_fifowrite(struct knote *kn, long hint) 430 { 431 struct socket *so = (struct socket *)kn->kn_hook; 432 433 kn->kn_data = sbspace(&so->so_snd); 434 if (so->so_state & SS_CANTSENDMORE) { 435 kn->kn_flags |= EV_EOF; 436 return (1); 437 } 438 kn->kn_flags &= ~EV_EOF; 439 return (kn->kn_data >= so->so_snd.sb_lowat); 440 } 441 442 /* 443 * fifo_poll(struct vnode *a_vp, int a_events, struct ucred *a_cred, 444 * struct thread *a_td) 445 */ 446 /* ARGSUSED */ 447 static int 448 fifo_poll(struct vop_poll_args *ap) 449 { 450 struct file filetmp; 451 int events, revents = 0; 452 453 events = ap->a_events & 454 (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND); 455 if (events) { 456 /* 457 * If POLLIN or POLLRDNORM is requested and POLLINIGNEOF is 458 * not, then convert the first two to the last one. This 459 * tells the socket poll function to ignore EOF so that we 460 * block if there is no writer (and no data). Callers can 461 * set POLLINIGNEOF to get non-blocking behavior. 462 */ 463 if (events & (POLLIN | POLLRDNORM) && 464 !(events & POLLINIGNEOF)) { 465 events &= ~(POLLIN | POLLRDNORM); 466 events |= POLLINIGNEOF; 467 } 468 469 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 470 if (filetmp.f_data) 471 revents |= soo_poll(&filetmp, events, ap->a_cred); 472 473 /* Reverse the above conversion. */ 474 if ((revents & POLLINIGNEOF) && 475 !(ap->a_events & POLLINIGNEOF)) { 476 revents |= (ap->a_events & (POLLIN | POLLRDNORM)); 477 revents &= ~POLLINIGNEOF; 478 } 479 } 480 events = ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND); 481 if (events) { 482 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 483 if (filetmp.f_data) 484 revents |= soo_poll(&filetmp, events, ap->a_cred); 485 } 486 return (revents); 487 } 488 489 /* 490 * fifo_inactive(struct vnode *a_vp, struct thread *a_td) 491 */ 492 static int 493 fifo_inactive(struct vop_inactive_args *ap) 494 { 495 return (0); 496 } 497 498 /* 499 * This is a noop, simply returning what one has been given. 500 * 501 * fifo_bmap(struct vnode *a_vp, off_t a_loffset, struct vnode **a_vpp, 502 * off_t *a_doffsetp, int *a_runp, int *a_runb) 503 */ 504 static int 505 fifo_bmap(struct vop_bmap_args *ap) 506 { 507 if (ap->a_vpp != NULL) 508 *ap->a_vpp = ap->a_vp; 509 if (ap->a_doffsetp != NULL) 510 *ap->a_doffsetp = ap->a_loffset; 511 if (ap->a_runp != NULL) 512 *ap->a_runp = 0; 513 if (ap->a_runb != NULL) 514 *ap->a_runb = 0; 515 return (0); 516 } 517 518 /* 519 * Device close routine 520 * 521 * fifo_close(struct vnode *a_vp, int a_fflag, struct ucred *a_cred, 522 * struct thread *a_td) 523 */ 524 /* ARGSUSED */ 525 static int 526 fifo_close(struct vop_close_args *ap) 527 { 528 struct vnode *vp = ap->a_vp; 529 struct fifoinfo *fip = vp->v_fifoinfo; 530 int error1, error2; 531 532 if (ap->a_fflag & FREAD) { 533 fip->fi_readers--; 534 if (fip->fi_readers == 0) 535 socantsendmore(fip->fi_writesock); 536 } 537 if (ap->a_fflag & FWRITE) { 538 fip->fi_writers--; 539 if (fip->fi_writers == 0) 540 socantrcvmore(fip->fi_readsock); 541 } 542 if (vp->v_usecount > 1) { 543 vop_stdclose(ap); 544 return (0); 545 } 546 error1 = soclose(fip->fi_readsock, FNONBLOCK); 547 error2 = soclose(fip->fi_writesock, FNONBLOCK); 548 FREE(fip, M_FIFOINFO); 549 vp->v_fifoinfo = NULL; 550 if (error1) 551 return (error1); 552 vop_stdclose(ap); 553 return (error2); 554 } 555 556 557 /* 558 * Print out internal contents of a fifo vnode. 559 */ 560 int 561 fifo_printinfo(struct vnode *vp) 562 { 563 struct fifoinfo *fip = vp->v_fifoinfo; 564 565 printf(", fifo with %ld readers and %ld writers", 566 fip->fi_readers, fip->fi_writers); 567 return (0); 568 } 569 570 /* 571 * Print out the contents of a fifo vnode. 572 * 573 * fifo_print(struct vnode *a_vp) 574 */ 575 static int 576 fifo_print(struct vop_print_args *ap) 577 { 578 printf("tag VT_NON"); 579 fifo_printinfo(ap->a_vp); 580 printf("\n"); 581 return (0); 582 } 583 584 /* 585 * Return POSIX pathconf information applicable to fifo's. 586 * 587 * fifo_pathconf(struct vnode *a_vp, int a_name, int *a_retval) 588 */ 589 int 590 fifo_pathconf(struct vop_pathconf_args *ap) 591 { 592 switch (ap->a_name) { 593 case _PC_LINK_MAX: 594 *ap->a_retval = LINK_MAX; 595 return (0); 596 case _PC_PIPE_BUF: 597 *ap->a_retval = PIPE_BUF; 598 return (0); 599 case _PC_CHOWN_RESTRICTED: 600 *ap->a_retval = 1; 601 return (0); 602 default: 603 return (EINVAL); 604 } 605 /* NOTREACHED */ 606 } 607 608 /* 609 * Fifo advisory byte-level locks. 610 * 611 * fifo_advlock(struct vnode *a_vp, caddr_t a_id, int a_op, struct flock *a_fl, 612 * int a_flags) 613 */ 614 /* ARGSUSED */ 615 static int 616 fifo_advlock(struct vop_advlock_args *ap) 617 { 618 return ((ap->a_flags & F_POSIX) ? EINVAL : EOPNOTSUPP); 619 } 620 621 /* 622 * Fifo bad operation 623 */ 624 static int 625 fifo_badop(void) 626 { 627 panic("fifo_badop called"); 628 /* NOTREACHED */ 629 } 630