Example #1
0
/**
 * 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;
}
Example #2
0
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;
}