struct dentry *lzfs_get_parent(struct dentry *child) { vnode_t *vcp = LZFS_ITOV(child->d_inode); vnode_t *vp; int error = 0; struct dentry *dentry = NULL; const struct cred *cred = get_current_cred(); SENTRY; error = zfs_lookup(vcp, "..", &vp, NULL, 0 , NULL, (struct cred *) cred, NULL, NULL, NULL); put_cred(cred); tsd_exit(); SEXIT; if (error) { if (error == ENOENT) { printk(KERN_WARNING "Try to get new dentry \n"); return d_splice_alias(NULL, dentry); } else { printk(KERN_WARNING "Unable to get dentry \n"); return ERR_PTR(-error); } } if (LZFS_VTOI(vp)) dentry = d_obtain_alias(LZFS_VTOI(vp)); return dentry; }
/* ARGSUSED */ int zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp, int flags, cred_t *cr, int *direntflags, pathname_t *realpnp) { zfs_sb_t *zsb = ITOZSB(dip); struct inode *ip; znode_t *dzp; int error; ZFS_ENTER(zsb); if (zsb->z_shares_dir == 0) { ZFS_EXIT(zsb); return (ENOTSUP); } error = zfs_zget(zsb, zsb->z_shares_dir, &dzp); if (error) { ZFS_EXIT(zsb); return (error); } error = zfs_lookup(ZTOI(dzp), name, &ip, 0, cr, NULL, NULL); iput(ZTOI(dzp)); ZFS_EXIT(zsb); return (error); }
zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) #endif { cred_t *cr = CRED(); struct inode *ip; int error; fstrans_cookie_t cookie; if (dlen(dentry) > ZFS_MAXNAMELEN) return (ERR_PTR(-ENAMETOOLONG)); crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL); spl_fstrans_unmark(cookie); ASSERT3S(error, <=, 0); crfree(cr); spin_lock(&dentry->d_lock); dentry->d_time = jiffies; #ifndef HAVE_S_D_OP d_set_d_op(dentry, &zpl_dentry_operations); #endif /* HAVE_S_D_OP */ spin_unlock(&dentry->d_lock); if (error) { if (error == -ENOENT) return (d_splice_alias(NULL, dentry)); else return (ERR_PTR(error)); } return (d_splice_alias(ip, dentry)); }
static int zpl_xattr_get_dir(struct inode *ip, const char *name, void *value, size_t size, cred_t *cr) { struct inode *dxip = NULL; struct inode *xip = NULL; loff_t pos = 0; int error; /* Lookup the xattr directory */ error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL); if (error) goto out; /* Lookup a specific xattr name in the directory */ error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL); if (error) goto out; if (!size) { error = i_size_read(xip); goto out; } if (size < i_size_read(xip)) { error = -ERANGE; goto out; } error = zpl_read_common(xip, value, size, &pos, UIO_SYSSPACE, 0, cr); out: if (xip) iput(xip); if (dxip) iput(dxip); 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 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)); }
int main(int argc, char** argv) { int i, n, off; int fd[99]; spa_t *spa; dnode_phys_t dn; char buf[512]; zfs_init(); if (argc == 1) { static char *av[] = { "zfstest", "/dev/da0p2", "/dev/da1p2", "/dev/da2p2", NULL, }; argc = 4; argv = av; } for (i = 1; i < argc; i++) { fd[i] = open(argv[i], O_RDONLY); if (fd[i] < 0) continue; if (vdev_probe(vdev_read, &fd[i], NULL) != 0) close(fd[i]); } spa_all_status(); spa = STAILQ_FIRST(&zfs_pools); if (!spa || zfs_mount_pool(spa)) exit(1); if (zfs_lookup(spa, "zfs.c", &dn)) exit(1); off = 0; do { n = zfs_read(spa, &dn, buf, 512, off); write(1, buf, n); off += n; } while (n == 512); }
static ssize_t zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr) { struct inode *ip = xf->inode; struct inode *dxip = NULL; int error; /* Lookup the xattr directory */ error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL); if (error) { if (error == -ENOENT) error = 0; return (error); } error = zpl_xattr_readdir(dxip, xf); iput(dxip); return (error); }
static struct dentry * zpl_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { cred_t *cr = CRED(); struct inode *ip; int error; crhold(cr); error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL); ASSERT3S(error, <=, 0); crfree(cr); if (error) { if (error == -ENOENT) return d_splice_alias(NULL, dentry); else return ERR_PTR(error); } return d_splice_alias(ip, dentry); }
static ssize_t zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr) { struct inode *ip = xf->inode; struct inode *dxip = NULL; int error; /* Lookup the xattr directory */ error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL); if (error) { if (error == -ENOENT) error = 0; return (error); } /* Fill provided buffer via zpl_zattr_filldir helper */ error = -zfs_readdir(dxip, (void *)xf, zpl_xattr_filldir, &pos, cr); VN_RELE(dxip); return (error); }
int main(int argc, char** argv) { char buf[512]; int fd[100]; struct stat sb; dnode_phys_t dn; spa_t *spa; off_t off; ssize_t n; int i; zfs_init(); if (argc == 1) { static char *av[] = { "zfstest", "COPYRIGHT", "/dev/da0p2", "/dev/da1p2", "/dev/da2p2", NULL, }; argc = 5; argv = av; } for (i = 2; i < argc; i++) { fd[i] = open(argv[i], O_RDONLY); if (fd[i] < 0) continue; if (vdev_probe(vdev_read, &fd[i], NULL) != 0) close(fd[i]); } spa_all_status(); spa = STAILQ_FIRST(&zfs_pools); if (spa == NULL) { fprintf(stderr, "no pools\n"); exit(1); } if (zfs_mount_pool(spa)) { fprintf(stderr, "can't mount pool\n"); exit(1); } if (zfs_lookup(spa, argv[1], &dn)) { fprintf(stderr, "can't lookup\n"); exit(1); } if (zfs_dnode_stat(spa, &dn, &sb)) { fprintf(stderr, "can't stat\n"); exit(1); } off = 0; do { n = sb.st_size - off; n = n > sizeof(buf) ? sizeof(buf) : n; n = zfs_read(spa, &dn, buf, n, off); if (n < 0) { fprintf(stderr, "zfs_read failed\n"); exit(1); } write(1, buf, n); off += n; } while (off < sb.st_size); return (0); }
static EFI_STATUS load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize) { spa_t *spa; struct zfsmount zfsmount; dnode_phys_t dn; struct stat st; int err; void *buf; EFI_STATUS status; spa = devinfo->devdata; DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name, devpath_str(devinfo->devpath)); if ((err = zfs_spa_init(spa)) != 0) { DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) { DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) { if (err == ENOENT) { DPRINTF("Failed to find '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_NOT_FOUND); } printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) { printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf)) != EFI_SUCCESS) { printf("Failed to allocate load buffer %zu for pool '%s' for '%s' " "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status)); return (EFI_INVALID_PARAMETER); } if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) { printf("Failed to read node from %s (%d)\n", spa->spa_name, err); (void)bs->FreePool(buf); return (EFI_INVALID_PARAMETER); } *bufsize = st.st_size; *bufp = buf; return (EFI_SUCCESS); }
static int lzfs_xattr_security_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) #endif { vnode_t *vp; vnode_t *dvp; vnode_t *xvp; vattr_t *vap; int err = 0; const struct cred *cred = get_current_cred(); struct iovec iov = { .iov_base = (void *) value, .iov_len = size, }; char *xattr_name = NULL; uio_t uio = { .uio_iov = &iov, .uio_resid = size, .uio_iovcnt = 1, .uio_loffset = (offset_t)0, .uio_limit = MAXOFFSET_T, .uio_segflg = UIO_SYSSPACE, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) dvp = LZFS_ITOV(inode); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) dvp = LZFS_ITOV(dentry->d_inode); #endif err = zfs_lookup(dvp, NULL, &vp, NULL, LOOKUP_XATTR | CREATE_XATTR_DIR, NULL, (struct cred *) cred, NULL, NULL, NULL); if(err) { return -err; } if(!value) { err =zfs_remove(vp, (char *) name, (struct cred *)cred, NULL, 0); return -err; } vap = kmalloc(sizeof(vattr_t), GFP_KERNEL); ASSERT(vap != NULL); memset(vap, 0, sizeof(vap)); vap->va_type = VREG; vap->va_mode = 0644; vap->va_mask = AT_TYPE|AT_MODE; vap->va_uid = current_fsuid(); vap->va_gid = current_fsgid(); xattr_name = kzalloc(strlen(name) + 10, GFP_KERNEL); xattr_name = strncpy(xattr_name, "security.", 9); xattr_name = strncat(xattr_name, name, strlen(name)); err = zfs_create(vp, xattr_name, vap, 0, 0644, &xvp, (struct cred *)cred, 0, NULL, NULL); kfree(vap); kfree(xattr_name); if(err) { return -err; } err = zfs_write(xvp, &uio, 0, (cred_t *)cred, NULL); put_cred(cred); if(err) { return -err; } return -err; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) static size_t lzfs_xattr_security_list(struct inode *inode, char *list, size_t list_size, const char *name, size_t name_len) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) static size_t lzfs_xattr_security_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len, int type) #endif { const size_t total_len = name_len + 1; if (list && total_len <= list_size) { memcpy(list, name, name_len); list[name_len] = '\0'; } return total_len; } int lzfs_init_security(struct dentry *dentry, struct inode *dir) { int err; size_t len; void *value; char *name; err = security_inode_init_security(dentry->d_inode, dir, &name, &value, &len); if (err) { if (err == -EOPNOTSUPP) return 0; return err; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) err = lzfs_xattr_security_set(dentry->d_inode, name, value, len, 0); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) err = lzfs_xattr_security_set(dentry, name, value, len, 0, 0); #endif kfree(name); kfree(value); return err; } struct xattr_handler lzfs_xattr_security_handler = { .prefix = XATTR_SECURITY_PREFIX, .list = lzfs_xattr_security_list, .get = lzfs_xattr_security_get, .set = lzfs_xattr_security_set, };
static int zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, size_t size, int flags, cred_t *cr) { struct inode *dxip = NULL; struct inode *xip = NULL; vattr_t *vap = NULL; ssize_t wrote; int lookup_flags, error; const int xattr_mode = S_IFREG | 0644; /* * Lookup the xattr directory. When we're adding an entry pass * CREATE_XATTR_DIR to ensure the xattr directory is created. * When removing an entry this flag is not passed to avoid * unnecessarily creating a new xattr directory. */ lookup_flags = LOOKUP_XATTR; if (value != NULL) lookup_flags |= CREATE_XATTR_DIR; error = -zfs_lookup(ip, NULL, &dxip, lookup_flags, cr, NULL, NULL); if (error) goto out; /* Lookup a specific xattr name in the directory */ error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL); if (error && (error != -ENOENT)) goto out; error = 0; /* Remove a specific name xattr when value is set to NULL. */ if (value == NULL) { if (xip) error = -zfs_remove(dxip, (char *)name, cr); goto out; } /* Lookup failed create a new xattr. */ if (xip == NULL) { vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); vap->va_mode = xattr_mode; vap->va_mask = ATTR_MODE; vap->va_uid = crgetfsuid(cr); vap->va_gid = crgetfsgid(cr); error = -zfs_create(dxip, (char *)name, vap, 0, 0644, &xip, cr, 0, NULL); if (error) goto out; } ASSERT(xip != NULL); error = -zfs_freesp(ITOZ(xip), 0, 0, xattr_mode, TRUE); if (error) goto out; wrote = zpl_write_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr); if (wrote < 0) error = wrote; out: if (vap) kmem_free(vap, sizeof(vattr_t)); if (xip) iput(xip); if (dxip) iput(dxip); if (error == -ENOENT) error = -ENODATA; ASSERT3S(error, <=, 0); return (error); }
zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) #endif { cred_t *cr = CRED(); struct inode *ip; int error; fstrans_cookie_t cookie; pathname_t *ppn = NULL; pathname_t pn; zfs_sb_t *zsb = dentry->d_sb->s_fs_info; if (dlen(dentry) > ZFS_MAXNAMELEN) return (ERR_PTR(-ENAMETOOLONG)); crhold(cr); cookie = spl_fstrans_mark(); /* If we are a case insensitive fs, we need the real name */ if (zsb->z_case == ZFS_CASE_INSENSITIVE) { pn.pn_bufsize = ZFS_MAXNAMELEN; pn.pn_buf = kmem_zalloc(ZFS_MAXNAMELEN, KM_SLEEP); ppn = &pn; } error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, ppn); spl_fstrans_unmark(cookie); ASSERT3S(error, <=, 0); crfree(cr); spin_lock(&dentry->d_lock); dentry->d_time = jiffies; #ifndef HAVE_S_D_OP d_set_d_op(dentry, &zpl_dentry_operations); #endif /* HAVE_S_D_OP */ spin_unlock(&dentry->d_lock); if (error) { if (ppn) kmem_free(pn.pn_buf, ZFS_MAXNAMELEN); if (error == -ENOENT) return (d_splice_alias(NULL, dentry)); else return (ERR_PTR(error)); } /* * If we are case insensitive, call the correct function * to install the name. */ if (ppn) { struct dentry *new_dentry; struct qstr ci_name; ci_name.name = pn.pn_buf; ci_name.len = strlen(pn.pn_buf); new_dentry = d_add_ci(dentry, ip, &ci_name); kmem_free(pn.pn_buf, ZFS_MAXNAMELEN); return (new_dentry); } else { return (d_splice_alias(ip, dentry)); } }
int main(int argc, char** argv) { char buf[512], hash[33]; MD5_CTX ctx; struct stat sb; struct zfsmount zfsmnt; dnode_phys_t dn; #if 0 uint64_t rootobj; #endif spa_t *spa; off_t off; ssize_t n; int i, failures, *fd; zfs_init(); if (argc == 1) { static char *av[] = { "zfsboottest", "/dev/gpt/system0", "/dev/gpt/system1", "-", "/boot/zfsloader", "/boot/support.4th", "/boot/kernel/kernel", NULL, }; argc = sizeof(av) / sizeof(av[0]) - 1; argv = av; } for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-") == 0) break; } fd = malloc(sizeof(fd[0]) * (i - 1)); if (fd == NULL) errx(1, "Unable to allocate memory."); for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-") == 0) break; fd[i - 1] = open(argv[i], O_RDONLY); if (fd[i - 1] == -1) { warn("open(%s) failed", argv[i]); continue; } if (vdev_probe(vdev_read, &fd[i - 1], NULL) != 0) { warnx("vdev_probe(%s) failed", argv[i]); close(fd[i - 1]); } } spa_all_status(); spa = STAILQ_FIRST(&zfs_pools); if (spa == NULL) { fprintf(stderr, "no pools\n"); exit(1); } if (zfs_spa_init(spa)) { fprintf(stderr, "can't init pool\n"); exit(1); } #if 0 if (zfs_get_root(spa, &rootobj)) { fprintf(stderr, "can't get root\n"); exit(1); } if (zfs_mount(spa, rootobj, &zfsmnt)) { #else if (zfs_mount(spa, 0, &zfsmnt)) { fprintf(stderr, "can't mount\n"); exit(1); } #endif printf("\n"); for (++i, failures = 0; i < argc; i++) { if (zfs_lookup(&zfsmnt, argv[i], &dn)) { fprintf(stderr, "%s: can't lookup\n", argv[i]); failures++; continue; } if (zfs_dnode_stat(spa, &dn, &sb)) { fprintf(stderr, "%s: can't stat\n", argv[i]); failures++; continue; } off = 0; MD5Init(&ctx); do { n = sb.st_size - off; n = n > sizeof(buf) ? sizeof(buf) : n; n = zfs_read(spa, &dn, buf, n, off); if (n < 0) { fprintf(stderr, "%s: zfs_read failed\n", argv[i]); failures++; break; } MD5Update(&ctx, buf, n); off += n; } while (off < sb.st_size); if (off < sb.st_size) continue; MD5End(&ctx, hash); printf("%s %s\n", hash, argv[i]); } return (failures == 0 ? 0 : 1); }
zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) #endif { cred_t *cr = CRED(); struct inode *ip; int error; fstrans_cookie_t cookie; pathname_t *ppn = NULL; pathname_t pn; int zfs_flags = 0; zfs_sb_t *zsb = dentry->d_sb->s_fs_info; if (dlen(dentry) > ZFS_MAX_DATASET_NAME_LEN) return (ERR_PTR(-ENAMETOOLONG)); crhold(cr); cookie = spl_fstrans_mark(); /* If we are a case insensitive fs, we need the real name */ if (zsb->z_case == ZFS_CASE_INSENSITIVE) { zfs_flags = FIGNORECASE; pn_alloc(&pn); ppn = &pn; } error = -zfs_lookup(dir, dname(dentry), &ip, zfs_flags, cr, NULL, ppn); spl_fstrans_unmark(cookie); ASSERT3S(error, <=, 0); crfree(cr); spin_lock(&dentry->d_lock); dentry->d_time = jiffies; #ifndef HAVE_S_D_OP d_set_d_op(dentry, &zpl_dentry_operations); #endif /* HAVE_S_D_OP */ spin_unlock(&dentry->d_lock); if (error) { /* * If we have a case sensitive fs, we do not want to * insert negative entries, so return NULL for ENOENT. * Fall through if the error is not ENOENT. Also free memory. */ if (ppn) { pn_free(ppn); if (error == -ENOENT) return (NULL); } if (error == -ENOENT) return (d_splice_alias(NULL, dentry)); else return (ERR_PTR(error)); } /* * If we are case insensitive, call the correct function * to install the name. */ if (ppn) { struct dentry *new_dentry; struct qstr ci_name; ci_name.name = pn.pn_buf; ci_name.len = strlen(pn.pn_buf); new_dentry = d_add_ci(dentry, ip, &ci_name); pn_free(ppn); return (new_dentry); } else { return (d_splice_alias(ip, dentry)); } }
static int zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, size_t size, int flags, cred_t *cr) { struct inode *dxip = NULL; struct inode *xip = NULL; vattr_t *vap = NULL; ssize_t wrote; int error; const int xattr_mode = S_IFREG | 0644; /* Lookup the xattr directory and create it if required. */ error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR | CREATE_XATTR_DIR, cr, NULL, NULL); if (error) goto out; /* Lookup a specific xattr name in the directory */ error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL); if (error && (error != -ENOENT)) goto out; error = 0; /* Remove a specific name xattr when value is set to NULL. */ if (value == NULL) { if (xip) error = -zfs_remove(dxip, (char *)name, cr); goto out; } /* Lookup failed create a new xattr. */ if (xip == NULL) { vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); vap->va_mode = xattr_mode; vap->va_mask = ATTR_MODE; vap->va_uid = crgetfsuid(cr); vap->va_gid = crgetfsgid(cr); error = -zfs_create(dxip, (char *)name, vap, 0, 0644, &xip, cr, 0, NULL); if (error) goto out; } ASSERT(xip != NULL); error = -zfs_freesp(ITOZ(xip), 0, 0, xattr_mode, TRUE); if (error) goto out; wrote = zpl_write_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr); if (wrote < 0) error = wrote; out: if (vap) kmem_free(vap, sizeof(vattr_t)); if (xip) VN_RELE(xip); if (dxip) VN_RELE(dxip); if (error == -ENOENT) error = -ENODATA; ASSERT3S(error, <=, 0); return (error); }