static int sfs_namefile(struct inode *node, struct iobuf *iob) { struct sfs_disk_entry *entry; if (iob->io_resid <= 2 || (entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { return -E_NO_MEM; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret; uint32_t ino; char *ptr = iob->io_base + iob->io_resid; size_t alen, resid = iob->io_resid - 2; vop_ref_inc(node); while ((ino = sin->ino) != SFS_BLKN_ROOT) { struct inode *parent; if ((ret = sfs_load_parent(sfs, sin, &parent)) != 0) { goto failed; } vop_ref_dec(node); node = parent, sin = vop_info(node, sfs_inode); assert(ino != sin->ino && sin->din->type == SFS_TYPE_DIR); if ((ret = trylock_sin(sin)) != 0) { goto failed; } ret = sfs_dirent_findino_nolock(sfs, sin, ino, entry); unlock_sin(sin); if (ret != 0) { goto failed; } if ((alen = strlen(entry->name) + 1) > resid) { goto failed_nomem; } resid -= alen, ptr -= alen; memcpy(ptr, entry->name, alen - 1); ptr[alen - 1] = '/'; } vop_ref_dec(node); alen = iob->io_resid - resid - 2; ptr = memmove(iob->io_base + 1, ptr, alen); ptr[-1] = '/', ptr[alen] = '\0'; iobuf_skip(iob, alen); kfree(entry); return 0; failed_nomem: ret = -E_NO_MEM; failed: vop_ref_dec(node); kfree(entry); return ret; }
static int pipe_inode_write(struct inode *node, struct iobuf *iob) { struct pipe_inode *pin = vop_info(node, pipe_inode); if (pin->pin_type != PIN_WRONLY) { return -E_INVAL; } size_t ret; if ((ret = pipe_state_write(pin->state, iob->io_base, iob->io_resid)) != 0) { iobuf_skip(iob, ret); } return 0; }
static int pipe_inode_namefile(struct inode *node, struct iobuf *iob) { struct pipe_inode *pin = vop_info(node, pipe_inode); size_t len = (pin->name != NULL) ? strlen(pin->name) : 0; if (iob->io_resid < len + 1) { return -E_NO_MEM; } if (pin->name != NULL) { memcpy(iob->io_base, pin->name, len); } ((char *)(iob->io_base))[len++] = '\0'; iobuf_skip(iob, len); return 0; }
static int pipe_inode_write(struct inode *node, struct iobuf *iob, int io_flags) { bool no_block = (io_flags & O_NONBLOCK) ? 1 : 0; struct pipe_inode *pin = vop_info(node, pipe_inode); if (pin->pin_type != PIN_WRONLY) { return -E_INVAL; } size_t ret; if ((ret = pipe_state_write(pin->state, iob->io_base, iob->io_resid, no_block)) != 0) { iobuf_skip(iob, ret); } return 0; }
/* * iobuf_move_zeros - set io buffer zero * @copiedp: the size of data memcopied */ int iobuf_move_zeros(struct iobuf *iob, size_t len, size_t *copiedp) { size_t alen; if ((alen = iob->io_resid) > len) { alen = len; } if (alen > 0) { memset(iob->io_base, 0, alen); iobuf_skip(iob, alen), len -= alen; } if (copiedp != NULL) { *copiedp = alen; } return (len == 0) ? 0 : -E_NO_MEM; }
/* * sfs_io - Rd/Wr file. the wrapper of sfs_io_nolock with lock protect */ static inline int sfs_io(struct inode *node, struct iobuf *iob, bool write) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret; lock_sin(sin); { size_t alen = iob->io_resid; ret = sfs_io_nolock(sfs, sin, iob->io_base, iob->io_offset, &alen, write); if (alen != 0) { iobuf_skip(iob, alen); } } unlock_sin(sin); return ret; }
/* iobuf_move - move data (iob->io_base ---> data OR data --> iob->io.base) in memory * @copiedp: the size of data memcopied * * iobuf_move may be called repeatedly on the same io to transfer * additional data until the available buffer space the io refers to * is exhausted. */ int iobuf_move(struct iobuf *iob, void *data, size_t len, bool m2b, size_t *copiedp) { size_t alen; if ((alen = iob->io_resid) > len) { alen = len; } if (alen > 0) { void *src = iob->io_base, *dst = data; if (m2b) { void *tmp = src; src = dst, dst = tmp; } memmove(dst, src, alen); iobuf_skip(iob, alen), len -= alen; } if (copiedp != NULL) { *copiedp = alen; } return (len == 0) ? 0 : -E_NO_MEM; }