static int zpl_sync_fs(struct super_block *sb, int wait) { fstrans_cookie_t cookie; cred_t *cr = CRED(); int error; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_sync(sb, wait, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_rmdir(struct inode * dir, struct dentry *dentry) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_rmdir(dir, dname(dentry), NULL, cr, 0); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
/* * Linux 2.6.x - 2.6.34 API, * Through 2.6.34 the nfsd kernel server would pass a NULL 'file struct *' * to the fops->fsync() hook. For this reason, we must be careful not to * use filp unconditionally. */ static int zpl_fsync(struct file *filp, struct dentry *dentry, int datasync) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_fsync(dentry->d_inode, datasync, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static ssize_t zpl_iter_read_common(struct kiocb *kiocb, const struct iovec *iovp, unsigned long nr_segs, size_t count, uio_seg_t seg, size_t skip) { cred_t *cr = CRED(); struct file *filp = kiocb->ki_filp; ssize_t read; crhold(cr); read = zpl_read_common_iovec(filp->f_mapping->host, iovp, count, nr_segs, &kiocb->ki_pos, seg, filp->f_flags, cr, skip); crfree(cr); file_accessed(filp); return (read); }
static int zpl_iterate(struct file *filp, struct dir_context *ctx) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_readdir(file_inode(filp), ctx, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_commit_metadata(struct inode *inode) { cred_t *cr = CRED(); fstrans_cookie_t cookie; int error; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_fsync(inode, 0, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
/* * Get the "ucred" of a process. */ struct ucred_s * pgetucred(proc_t *p) { cred_t *cr; struct ucred_s *uc; mutex_enter(&p->p_crlock); cr = p->p_cred; crhold(cr); mutex_exit(&p->p_crlock); uc = cred2ucred(cr, p->p_pid, NULL, CRED()); crfree(cr); return (uc); }
/* * When relabeling a process, call out to the policies for the maximum * permission allowed for each object type we know about in its memory space, * and revoke access (in the least surprising ways we know) when necessary. * The process lock is not held here. */ void mac_proc_vm_revoke(struct thread *td) { struct ucred *cred; PROC_LOCK(td->td_proc); cred = crhold(td->td_proc->p_ucred); PROC_UNLOCK(td->td_proc); /* XXX freeze all other threads */ mac_proc_vm_revoke_recurse(td, cred, &td->td_proc->p_vmspace->vm_map); /* XXX allow other threads to continue */ crfree(cred); }
static int zpl_xattr_set(struct inode *ip, const char *name, const void *value, size_t size, int flags) { znode_t *zp = ITOZ(ip); zfs_sb_t *zsb = ZTOZSB(zp); cred_t *cr = CRED(); int error; crhold(cr); rw_enter(&ITOZ(ip)->z_xattr_lock, RW_WRITER); /* * Before setting the xattr check to see if it already exists. * This is done to ensure the following optional flags are honored. * * XATTR_CREATE: fail if xattr already exists * XATTR_REPLACE: fail if xattr does not exist */ error = __zpl_xattr_get(ip, name, NULL, 0, cr); if (error < 0) { if (error != -ENODATA) goto out; if ((error == -ENODATA) && (flags & XATTR_REPLACE)) goto out; } else { error = -EEXIST; if (flags & XATTR_CREATE) goto out; } /* Preferentially store the xattr as a SA for better performance */ if (zsb->z_use_sa && zsb->z_xattr_sa && zp->z_is_sa) { error = zpl_xattr_set_sa(ip, name, value, size, flags, cr); if (error == 0) goto out; } error = zpl_xattr_set_dir(ip, name, value, size, flags, cr); out: rw_exit(&ITOZ(ip)->z_xattr_lock); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
const char * zpl_follow_link(struct dentry *dentry, void **symlink_cookie) #endif { cred_t *cr = CRED(); struct inode *ip = dentry->d_inode; struct iovec iov; uio_t uio; char *link; int error; fstrans_cookie_t cookie; crhold(cr); iov.iov_len = MAXPATHLEN; iov.iov_base = link = kmem_zalloc(MAXPATHLEN, KM_SLEEP); uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_skip = 0; uio.uio_resid = (MAXPATHLEN - 1); uio.uio_segflg = UIO_SYSSPACE; cookie = spl_fstrans_mark(); error = -zfs_readlink(ip, &uio, cr); spl_fstrans_unmark(cookie); if (error) kmem_free(link, MAXPATHLEN); crfree(cr); #ifdef HAVE_FOLLOW_LINK_NAMEIDATA if (error) nd_set_link(nd, ERR_PTR(error)); else nd_set_link(nd, link); return (NULL); #else if (error) return (ERR_PTR(error)); else return (*symlink_cookie = link); #endif }
static int zpl_iterate(struct file *filp, struct dir_context *ctx) { struct dentry *dentry = filp->f_path.dentry; cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_readdir(dentry->d_inode, ctx, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static ssize_t zpl_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) { cred_t *cr = CRED(); ssize_t read; crhold(cr); read = zpl_read_common(filp->f_mapping->host, buf, len, *ppos, UIO_USERSPACE, filp->f_flags, cr); crfree(cr); if (read < 0) return (read); *ppos += read; return (read); }
/* * Linux 2.6.35 - 3.0 API, * As of 2.6.35 the dentry argument to the fops->fsync() hook was deemed * redundant. The dentry is still accessible via filp->f_path.dentry, * and we are guaranteed that filp will never be NULL. */ static int zpl_fsync(struct file *filp, int datasync) { struct inode *inode = filp->f_mapping->host; cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_fsync(inode, datasync, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static struct dentry * zpl_get_parent(struct dentry *child) { cred_t *cr = CRED(); struct inode *ip; int error; crhold(cr); error = -zfs_lookup(child->d_inode, "..", &ip, 0, cr, NULL, NULL); crfree(cr); ASSERT3S(error, <=, 0); if (error) return ERR_PTR(error); return zpl_dentry_obtain_alias(ip); }
static ssize_t zpl_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) { cred_t *cr = CRED(); ssize_t wrote; crhold(cr); wrote = zpl_write_common(filp->f_mapping->host, buf, len, *ppos, UIO_USERSPACE, filp->f_flags, cr); crfree(cr); if (wrote < 0) return (wrote); *ppos += wrote; return (wrote); }
/* * Passively intercepts the thread switch function to increase the thread * priority from a user priority to a kernel priority, reducing * syscall and trap overhead for the case where no switch occurs. * * Synchronizes td_ucred with p_ucred. This is used by system calls, * signal handling, faults, AST traps, and anything else that enters the * kernel from userland and provides the kernel with a stable read-only * copy of the process ucred. */ static __inline void userenter(struct thread *curtd, struct proc *curp) { struct ucred *ocred; struct ucred *ncred; curtd->td_release = lwkt_passive_release; if (curtd->td_ucred != curp->p_ucred) { ncred = crhold(curp->p_ucred); ocred = curtd->td_ucred; curtd->td_ucred = ncred; if (ocred) crfree(ocred); } }
static int zpl_rename(struct inode *sdip, struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_rename(sdip, dname(sdentry), tdip, dname(tdentry), cr, 0); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_open(struct inode *ip, struct file *filp) { cred_t *cr = CRED(); int error; error = generic_file_open(ip, filp); if (error) return (error); crhold(cr); error = -zfs_open(ip, filp->f_mode, filp->f_flags, cr); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
long zpl_fallocate_common(struct inode *ip, int mode, loff_t offset, loff_t len) { int error = -EOPNOTSUPP; #if defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) cred_t *cr = CRED(); flock64_t bf; loff_t olen; fstrans_cookie_t cookie; if (mode != (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) return (error); crhold(cr); if (offset < 0 || len <= 0) return (-EINVAL); spl_inode_lock(ip); olen = i_size_read(ip); if (offset > olen) { spl_inode_unlock(ip); return (0); } if (offset + len > olen) len = olen - offset; bf.l_type = F_WRLCK; bf.l_whence = 0; bf.l_start = offset; bf.l_len = len; bf.l_pid = 0; cookie = spl_fstrans_mark(); error = -zfs_space(ip, F_FREESP, &bf, FWRITE, offset, cr); spl_fstrans_unmark(cookie); spl_inode_unlock(ip); crfree(cr); #endif /* defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) */ ASSERT3S(error, <=, 0); return (error); }
int pts_alloc_external(int fflags, struct thread *td, struct file *fp, struct cdev *dev, const char *name) { int ok, error; struct tty *tp; struct pts_softc *psc; struct proc *p = td->td_proc; struct ucred *cred = td->td_ucred; /* Resource limiting. */ PROC_LOCK(p); error = racct_add(p, RACCT_NPTS, 1); if (error != 0) { PROC_UNLOCK(p); return (EAGAIN); } ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); if (!ok) { racct_sub(p, RACCT_NPTS, 1); PROC_UNLOCK(p); return (EAGAIN); } PROC_UNLOCK(p); /* Allocate TTY and softc. */ psc = malloc(sizeof(struct pts_softc), M_PTS, M_WAITOK|M_ZERO); cv_init(&psc->pts_inwait, "ptsin"); cv_init(&psc->pts_outwait, "ptsout"); psc->pts_unit = -1; psc->pts_cdev = dev; psc->pts_cred = crhold(cred); tp = tty_alloc(&pts_class, psc); knlist_init_mtx(&psc->pts_inpoll.si_note, tp->t_mtx); knlist_init_mtx(&psc->pts_outpoll.si_note, tp->t_mtx); /* Expose the slave device as well. */ tty_makedev(tp, td->td_ucred, "%s", name); finit(fp, fflags, DTYPE_PTS, tp, &ptsdev_ops); return (0); }
cfs_file_t * kern_file_open(const char * filename, int flags, int mode, int *err) { struct nameidata nd; cfs_file_t *fp; register struct vnode *vp; int rc; extern struct fileops vnops; extern int nfiles; CFS_DECL_CONE_DATA; CFS_CONE_IN; nfiles++; MALLOC_ZONE(fp, cfs_file_t *, sizeof(cfs_file_t), M_FILE, M_WAITOK|M_ZERO); bzero(fp, sizeof(cfs_file_t)); fp->f_count = 1; LIST_CIRCLE(fp, f_list); NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, (char *)filename, current_proc()); if ((rc = vn_open(&nd, flags, mode)) != 0){ printf("filp_open failed at (%d)\n", rc); if (err != NULL) *err = rc; FREE_ZONE(fp, sizeof *fp, M_FILE); CFS_CONE_EX; return NULL; } vp = nd.ni_vp; fp->f_flag = flags & FMASK; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t)vp; fp->f_cred = current_proc()->p_ucred; /* * Hold cred to increase reference */ crhold(fp->f_cred); /* * vnode is locked inside vn_open for lookup, * we should release the lock before return */ VOP_UNLOCK(vp, 0, current_proc()); CFS_CONE_EX; return fp; }
static int zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size) { znode_t *zp = ITOZ(ip); cred_t *cr = CRED(); fstrans_cookie_t cookie; int error; crhold(cr); cookie = spl_fstrans_mark(); rw_enter(&zp->z_xattr_lock, RW_READER); error = __zpl_xattr_get(ip, name, value, size, cr); rw_exit(&zp->z_xattr_lock); spl_fstrans_unmark(cookie); crfree(cr); return (error); }
/* * Linux 3.1 - 3.x API, * As of 3.1 the responsibility to call filemap_write_and_wait_range() has * been pushed down in to the .fsync() vfs hook. Additionally, the i_mutex * lock is no longer held by the caller, for zfs we don't require the lock * to be held so we don't acquire it. */ static int zpl_fsync(struct file *filp, loff_t start, loff_t end, int datasync) { struct inode *inode = filp->f_mapping->host; cred_t *cr = CRED(); int error; error = filemap_write_and_wait_range(inode->i_mapping, start, end); if (error) return (error); crhold(cr); error = -zfs_fsync(inode, datasync, cr); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
void osi_Init(void) { static int once = 0; if (once++ > 0) /* just in case */ return; osi_InitGlock(); if (!afs_osicred_initialized) { #if defined(AFS_DARWIN80_ENV) afs_osi_ctxtp_initialized = 0; afs_osi_ctxtp = NULL; /* initialized in afs_Daemon since it has a proc reference that cannot be changed */ #endif #if defined(AFS_XBSD_ENV) /* Can't just invent one, must use crget() because of mutex */ afs_osi_credp = crdup(osi_curcred()); #elif defined(AFS_SUN5_ENV) afs_osi_credp = kcred; #else memset(&afs_osi_cred, 0, sizeof(afs_ucred_t)); #if defined(AFS_LINUX26_ENV) afs_set_cr_group_info(&afs_osi_cred, groups_alloc(0)); #endif #if defined(AFS_DARWIN80_ENV) afs_osi_cred.cr_ref = 1; /* kauth_cred_get_ref needs 1 existing ref */ #else # if !(defined(AFS_LINUX26_ENV) && defined(STRUCT_TASK_STRUCT_HAS_CRED)) crhold(&afs_osi_cred); /* don't let it evaporate */ # endif #endif afs_osi_credp = &afs_osi_cred; #endif afs_osicred_initialized = 1; } #ifdef AFS_SGI64_ENV osi_flid.fl_pid = osi_flid.fl_sysid = 0; #endif init_et_to_sys_error(); }
static int zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) { cred_t *cr = CRED(); vattr_t *vap; struct inode *ip; int error; crhold(cr); vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); zpl_vap_init(vap, dir, dentry, S_IFLNK | S_IRWXUGO, cr); error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0); kmem_free(vap, sizeof(vattr_t)); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_mkdir(struct inode *dir, struct dentry *dentry, zpl_umode_t mode) { cred_t *cr = CRED(); vattr_t *vap; struct inode *ip; int error; crhold(cr); vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); zpl_vap_init(vap, dir, dentry, mode | S_IFDIR, cr); error = -zfs_mkdir(dir, dname(dentry), vap, &ip, cr, 0, NULL); kmem_free(vap, sizeof(vattr_t)); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_release(struct inode *ip, struct file *filp) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; cookie = spl_fstrans_mark(); if (ITOZ(ip)->z_atime_dirty) zfs_mark_inode_dirty(ip); crhold(cr); error = -zfs_close(ip, filp->f_flags, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused, struct thread *td) { int error; struct filemon *filemon; filemon = malloc(sizeof(*filemon), M_FILEMON, M_WAITOK | M_ZERO); sx_init(&filemon->lock, "filemon"); refcount_init(&filemon->refcnt, 1); filemon->cred = crhold(td->td_ucred); error = devfs_set_cdevpriv(filemon, filemon_dtr); if (error != 0) filemon_release(filemon); return (error); }
static int zpl_mknod(struct inode *dir, struct dentry *dentry, zpl_umode_t mode, dev_t rdev) { cred_t *cr = CRED(); struct inode *ip; vattr_t *vap; int error; fstrans_cookie_t cookie; /* * We currently expect Linux to supply rdev=0 for all sockets * and fifos, but we want to know if this behavior ever changes. */ if (S_ISSOCK(mode) || S_ISFIFO(mode)) ASSERT(rdev == 0); crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); zpl_vap_init(vap, dir, mode, cr); vap->va_rdev = rdev; cookie = spl_fstrans_mark(); error = -zfs_create(dir, dname(dentry), vap, 0, mode, &ip, cr, 0, NULL); if (error == 0) { d_instantiate(dentry, ip); error = zpl_xattr_security_init(ip, dir, &dentry->d_name); if (error == 0) error = zpl_init_acl(ip, dir); if (error) (void) zfs_remove(dir, dname(dentry), cr, 0); } spl_fstrans_unmark(cookie); kmem_free(vap, sizeof (vattr_t)); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static struct dentry * zpl_get_parent(struct dentry *child) { cred_t *cr = CRED(); fstrans_cookie_t cookie; struct inode *ip; int error; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_lookup(child->d_inode, "..", &ip, 0, cr, NULL, NULL); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); if (error) return (ERR_PTR(error)); return (zpl_dentry_obtain_alias(ip)); }