/** * v9fs_file_read - read from a file * @filep: file pointer to read * @data: data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ static ssize_t v9fs_file_read(struct file *filp, char __user * data, size_t count, loff_t * offset) { struct inode *inode = filp->f_path.dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); struct v9fs_fid *v9f = filp->private_data; struct v9fs_fcall *fcall = NULL; int fid = v9f->fid; int rsize = 0; int result = 0; int total = 0; int n; dprintk(DEBUG_VFS, "\n"); rsize = v9ses->maxdata - V9FS_IOHDRSZ; if (v9f->iounit != 0 && rsize > v9f->iounit) rsize = v9f->iounit; do { if (count < rsize) rsize = count; result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall); if (result < 0) { printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n", result); kfree(fcall); return total; } else *offset += result; n = copy_to_user(data, fcall->params.rread.data, result); if (n) { dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); kfree(fcall); return -EFAULT; } count -= result; data += result; total += result; kfree(fcall); if (result < rsize) break; } while (count); return total; }
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct v9fs_fcall *fcall = NULL; struct inode *inode = filp->f_path.dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); struct v9fs_fid *file = filp->private_data; unsigned int i, n, s; int fid = -1; int ret = 0; struct v9fs_stat stat; int over = 0; dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); fid = file->fid; if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) { kfree(file->rdir_fcall); file->rdir_fcall = NULL; } if (file->rdir_fcall) { n = file->rdir_fcall->params.rread.count; i = file->rdir_fpos; while (i < n) { s = v9fs_deserialize_stat( file->rdir_fcall->params.rread.data + i, n - i, &stat, v9ses->extended); if (s == 0) { dprintk(DEBUG_ERROR, "error while deserializing stat\n"); ret = -EIO; goto FreeStructs; } over = filldir(dirent, stat.name.str, stat.name.len, filp->f_pos, v9fs_qid2ino(&stat.qid), dt_type(&stat)); if (over) { file->rdir_fpos = i; file->rdir_pos = filp->f_pos; break; } i += s; filp->f_pos += s; } if (!over) { kfree(file->rdir_fcall); file->rdir_fcall = NULL; } } while (!over) { ret = v9fs_t_read(v9ses, fid, filp->f_pos, v9ses->maxdata-V9FS_IOHDRSZ, &fcall); if (ret < 0) { dprintk(DEBUG_ERROR, "error while reading: %d: %p\n", ret, fcall); goto FreeStructs; } else if (ret == 0) break; n = ret; i = 0; while (i < n) { s = v9fs_deserialize_stat(fcall->params.rread.data + i, n - i, &stat, v9ses->extended); if (s == 0) { dprintk(DEBUG_ERROR, "error while deserializing stat\n"); return -EIO; } over = filldir(dirent, stat.name.str, stat.name.len, filp->f_pos, v9fs_qid2ino(&stat.qid), dt_type(&stat)); if (over) { file->rdir_fcall = fcall; file->rdir_fpos = i; file->rdir_pos = filp->f_pos; fcall = NULL; break; } i += s; filp->f_pos += s; } kfree(fcall); } FreeStructs: kfree(fcall); return ret; }