int alq_open_flags(struct alq **alqp, const char *file, struct ucred *cred, int cmode, int size, int flags) { struct thread *td; struct nameidata nd; struct alq *alq; int oflags; int error; int vfslocked; KASSERT((size > 0), ("%s: size <= 0", __func__)); *alqp = NULL; td = curthread; NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, file, td); oflags = FWRITE | O_NOFOLLOW | O_CREAT; error = vn_open_cred(&nd, &oflags, cmode, 0, cred, NULL); if (error) return (error); vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); /* We just unlock so we hold a reference */ VOP_UNLOCK(nd.ni_vp, 0); VFS_UNLOCK_GIANT(vfslocked); alq = bsd_malloc(sizeof(*alq), M_ALD, M_WAITOK|M_ZERO); alq->aq_vp = nd.ni_vp; alq->aq_cred = crhold(cred); mtx_init(&alq->aq_mtx, "ALD Queue", NULL, MTX_SPIN|MTX_QUIET); alq->aq_buflen = size; alq->aq_entmax = 0; alq->aq_entlen = 0; alq->aq_freebytes = alq->aq_buflen; alq->aq_entbuf = bsd_malloc(alq->aq_buflen, M_ALD, M_WAITOK|M_ZERO); alq->aq_writehead = alq->aq_writetail = 0; if (flags & ALQ_ORDERED) alq->aq_flags |= AQ_ORDERED; if ((error = ald_add(alq)) != 0) { alq_destroy(alq); return (error); } *alqp = alq; return (0); }
/* * Create the queue data structure, allocate the buffer, and open the file. */ int alq_open(struct alq **alqp, const char *file, int size, int count) { struct file *f; struct ale *ale; struct ale *alp; struct alq *alq; char *bufp; int error; int i; *alqp = NULL; /* NB: no O_TRUNC */ f = filp_open(file, O_WRONLY | O_LARGEFILE | O_CREAT, 0644); if (IS_ERR(f)) return PTR_ERR(f); alq = kmalloc(sizeof(*alq), GFP_KERNEL); if (alq == NULL) { printk("%s: no memory for alq structure\n", __func__); error = -ENOMEM; goto bad1; } memset(alq, 0, sizeof(*alq)); alq->aq_entbuf = kmalloc(count * size, GFP_KERNEL); if (alq->aq_entbuf == NULL) { printk("%s: no memory for alq entbuf\n", __func__); error = -ENOMEM; goto bad2; } memset(alq->aq_entbuf, 0, count * size); alq->aq_first = kmalloc(sizeof(*ale) * count, GFP_KERNEL); if (alq->aq_first == NULL) { printk("%s: no memory for alq entries\n", __func__); error = -ENOMEM; goto bad3; } memset(alq->aq_first, 0, sizeof(*ale) * count); alq->aq_fp = f; alq->aq_entmax = count; alq->aq_entlen = size; alq->aq_entfree = alq->aq_first; spin_lock_init(&alq->aq_lock); init_waitqueue_head(&alq->aq_waitq); bufp = alq->aq_entbuf; ale = alq->aq_first; alp = NULL; /* Match up entries with buffers */ for (i = 0; i < count; i++) { if (alp) alp->ae_next = ale; ale->ae_data = bufp; alp = ale; ale++; bufp += size; } alp->ae_next = alq->aq_first; if ((error = ald_add(alq)) != 0) { printk("%s: unable to add alq, probably shutting down\n", __func__); goto bad4; } *alqp = alq; /* XXX bump module refcnt */ return (0); bad4: kfree(alq->aq_first); bad3: kfree(alq->aq_entbuf); bad2: kfree(alq); bad1: filp_close(f, /*XXX*/0); return error; }
/* * Create the queue data structure, allocate the buffer, and open the file. */ int alq_open(struct alq **alqp, const char *file, struct ucred *cred, int cmode, int size, int count) { struct thread *td; struct nameidata nd; struct ale *ale; struct ale *alp; struct alq *alq; char *bufp; int flags; int error; int i, vfslocked; *alqp = NULL; td = curthread; NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, file, td); flags = FWRITE | O_NOFOLLOW | O_CREAT; error = vn_open_cred(&nd, &flags, cmode, 0, cred, NULL); if (error) return (error); vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); /* We just unlock so we hold a reference */ VOP_UNLOCK(nd.ni_vp, 0); VFS_UNLOCK_GIANT(vfslocked); alq = malloc(sizeof(*alq), M_ALD, M_WAITOK|M_ZERO); alq->aq_entbuf = malloc(count * size, M_ALD, M_WAITOK|M_ZERO); alq->aq_first = malloc(sizeof(*ale) * count, M_ALD, M_WAITOK|M_ZERO); alq->aq_vp = nd.ni_vp; alq->aq_cred = crhold(cred); alq->aq_entmax = count; alq->aq_entlen = size; alq->aq_entfree = alq->aq_first; mtx_init(&alq->aq_mtx, "ALD Queue", NULL, MTX_SPIN|MTX_QUIET); bufp = alq->aq_entbuf; ale = alq->aq_first; alp = NULL; /* Match up entries with buffers */ for (i = 0; i < count; i++) { if (alp) alp->ae_next = ale; ale->ae_data = bufp; alp = ale; ale++; bufp += size; } alp->ae_next = alq->aq_first; if ((error = ald_add(alq)) != 0) return (error); *alqp = alq; return (0); }