aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p/vfs_file.c')
-rw-r--r--fs/9p/vfs_file.c93
1 files changed, 82 insertions, 11 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 52944d2249a4..041c52692284 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -120,23 +120,72 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
120} 120}
121 121
122/** 122/**
123 * v9fs_file_read - read from a file 123 * v9fs_file_readn - read from a file
124 * @filp: file pointer to read 124 * @filp: file pointer to read
125 * @data: data buffer to read data into 125 * @data: data buffer to read data into
126 * @udata: user data buffer to read data into
126 * @count: size of buffer 127 * @count: size of buffer
127 * @offset: offset at which to read data 128 * @offset: offset at which to read data
128 * 129 *
129 */ 130 */
131
132ssize_t
133v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
134 u64 offset)
135{
136 int n, total;
137 struct p9_fid *fid = filp->private_data;
138
139 P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid,
140 (long long unsigned) offset, count);
141
142 n = 0;
143 total = 0;
144 do {
145 n = p9_client_read(fid, data, udata, offset, count);
146 if (n <= 0)
147 break;
148
149 if (data)
150 data += n;
151 if (udata)
152 udata += n;
153
154 offset += n;
155 count -= n;
156 total += n;
157 } while (count > 0 && n == (fid->clnt->msize - P9_IOHDRSZ));
158
159 if (n < 0)
160 total = n;
161
162 return total;
163}
164
165/**
166 * v9fs_file_read - read from a file
167 * @filp: file pointer to read
168 * @udata: user data buffer to read data into
169 * @count: size of buffer
170 * @offset: offset at which to read data
171 *
172 */
173
130static ssize_t 174static ssize_t
131v9fs_file_read(struct file *filp, char __user * data, size_t count, 175v9fs_file_read(struct file *filp, char __user *udata, size_t count,
132 loff_t * offset) 176 loff_t * offset)
133{ 177{
134 int ret; 178 int ret;
135 struct p9_fid *fid; 179 struct p9_fid *fid;
136 180
137 P9_DPRINTK(P9_DEBUG_VFS, "\n"); 181 P9_DPRINTK(P9_DEBUG_VFS, "count %d offset %lld\n", count, *offset);
138 fid = filp->private_data; 182 fid = filp->private_data;
139 ret = p9_client_uread(fid, data, *offset, count); 183
184 if (count > (fid->clnt->msize - P9_IOHDRSZ))
185 ret = v9fs_file_readn(filp, NULL, udata, count, *offset);
186 else
187 ret = p9_client_read(fid, NULL, udata, *offset, count);
188
140 if (ret > 0) 189 if (ret > 0)
141 *offset += ret; 190 *offset += ret;
142 191
@@ -156,19 +205,38 @@ static ssize_t
156v9fs_file_write(struct file *filp, const char __user * data, 205v9fs_file_write(struct file *filp, const char __user * data,
157 size_t count, loff_t * offset) 206 size_t count, loff_t * offset)
158{ 207{
159 int ret; 208 int n, rsize, total = 0;
160 struct p9_fid *fid; 209 struct p9_fid *fid;
210 struct p9_client *clnt;
161 struct inode *inode = filp->f_path.dentry->d_inode; 211 struct inode *inode = filp->f_path.dentry->d_inode;
212 int origin = *offset;
162 213
163 P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, 214 P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
164 (int)count, (int)*offset); 215 (int)count, (int)*offset);
165 216
166 fid = filp->private_data; 217 fid = filp->private_data;
167 ret = p9_client_uwrite(fid, data, *offset, count); 218 clnt = fid->clnt;
168 if (ret > 0) { 219
169 invalidate_inode_pages2_range(inode->i_mapping, *offset, 220 rsize = fid->iounit;
170 *offset+ret); 221 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
171 *offset += ret; 222 rsize = clnt->msize - P9_IOHDRSZ;
223
224 do {
225 if (count < rsize)
226 rsize = count;
227
228 n = p9_client_write(fid, NULL, data+total, *offset+total,
229 rsize);
230 if (n <= 0)
231 break;
232 count -= n;
233 total += n;
234 } while (count > 0);
235
236 if (total > 0) {
237 invalidate_inode_pages2_range(inode->i_mapping, origin,
238 origin+total);
239 *offset += total;
172 } 240 }
173 241
174 if (*offset > inode->i_size) { 242 if (*offset > inode->i_size) {
@@ -176,7 +244,10 @@ v9fs_file_write(struct file *filp, const char __user * data,
176 inode->i_blocks = (inode->i_size + 512 - 1) >> 9; 244 inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
177 } 245 }
178 246
179 return ret; 247 if (n < 0)
248 return n;
249
250 return total;
180} 251}
181 252
182static const struct file_operations v9fs_cached_file_operations = { 253static const struct file_operations v9fs_cached_file_operations = {