aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c187
1 files changed, 123 insertions, 64 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 81f8bbf12f9f..5947628aefef 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -40,6 +40,7 @@
40#include "v9fs.h" 40#include "v9fs.h"
41#include "v9fs_vfs.h" 41#include "v9fs_vfs.h"
42#include "fid.h" 42#include "fid.h"
43#include "cache.h"
43 44
44static const struct inode_operations v9fs_dir_inode_operations; 45static const struct inode_operations v9fs_dir_inode_operations;
45static const struct inode_operations v9fs_dir_inode_operations_ext; 46static const struct inode_operations v9fs_dir_inode_operations_ext;
@@ -171,7 +172,6 @@ int v9fs_uflags2omode(int uflags, int extended)
171 172
172/** 173/**
173 * v9fs_blank_wstat - helper function to setup a 9P stat structure 174 * v9fs_blank_wstat - helper function to setup a 9P stat structure
174 * @v9ses: 9P session info (for determining extended mode)
175 * @wstat: structure to initialize 175 * @wstat: structure to initialize
176 * 176 *
177 */ 177 */
@@ -198,6 +198,39 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
198 wstat->extension = NULL; 198 wstat->extension = NULL;
199} 199}
200 200
201#ifdef CONFIG_9P_FSCACHE
202/**
203 * v9fs_alloc_inode - helper function to allocate an inode
204 * This callback is executed before setting up the inode so that we
205 * can associate a vcookie with each inode.
206 *
207 */
208
209struct inode *v9fs_alloc_inode(struct super_block *sb)
210{
211 struct v9fs_cookie *vcookie;
212 vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache,
213 GFP_KERNEL);
214 if (!vcookie)
215 return NULL;
216
217 vcookie->fscache = NULL;
218 vcookie->qid = NULL;
219 spin_lock_init(&vcookie->lock);
220 return &vcookie->inode;
221}
222
223/**
224 * v9fs_destroy_inode - destroy an inode
225 *
226 */
227
228void v9fs_destroy_inode(struct inode *inode)
229{
230 kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
231}
232#endif
233
201/** 234/**
202 * v9fs_get_inode - helper function to setup an inode 235 * v9fs_get_inode - helper function to setup an inode
203 * @sb: superblock 236 * @sb: superblock
@@ -207,65 +240,72 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
207 240
208struct inode *v9fs_get_inode(struct super_block *sb, int mode) 241struct inode *v9fs_get_inode(struct super_block *sb, int mode)
209{ 242{
243 int err;
210 struct inode *inode; 244 struct inode *inode;
211 struct v9fs_session_info *v9ses = sb->s_fs_info; 245 struct v9fs_session_info *v9ses = sb->s_fs_info;
212 246
213 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 247 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
214 248
215 inode = new_inode(sb); 249 inode = new_inode(sb);
216 if (inode) { 250 if (!inode) {
217 inode->i_mode = mode;
218 inode->i_uid = current_fsuid();
219 inode->i_gid = current_fsgid();
220 inode->i_blocks = 0;
221 inode->i_rdev = 0;
222 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
223 inode->i_mapping->a_ops = &v9fs_addr_operations;
224
225 switch (mode & S_IFMT) {
226 case S_IFIFO:
227 case S_IFBLK:
228 case S_IFCHR:
229 case S_IFSOCK:
230 if (!v9fs_extended(v9ses)) {
231 P9_DPRINTK(P9_DEBUG_ERROR,
232 "special files without extended mode\n");
233 return ERR_PTR(-EINVAL);
234 }
235 init_special_inode(inode, inode->i_mode,
236 inode->i_rdev);
237 break;
238 case S_IFREG:
239 inode->i_op = &v9fs_file_inode_operations;
240 inode->i_fop = &v9fs_file_operations;
241 break;
242 case S_IFLNK:
243 if (!v9fs_extended(v9ses)) {
244 P9_DPRINTK(P9_DEBUG_ERROR,
245 "extended modes used w/o 9P2000.u\n");
246 return ERR_PTR(-EINVAL);
247 }
248 inode->i_op = &v9fs_symlink_inode_operations;
249 break;
250 case S_IFDIR:
251 inc_nlink(inode);
252 if (v9fs_extended(v9ses))
253 inode->i_op = &v9fs_dir_inode_operations_ext;
254 else
255 inode->i_op = &v9fs_dir_inode_operations;
256 inode->i_fop = &v9fs_dir_operations;
257 break;
258 default:
259 P9_DPRINTK(P9_DEBUG_ERROR,
260 "BAD mode 0x%x S_IFMT 0x%x\n",
261 mode, mode & S_IFMT);
262 return ERR_PTR(-EINVAL);
263 }
264 } else {
265 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); 251 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
266 return ERR_PTR(-ENOMEM); 252 return ERR_PTR(-ENOMEM);
267 } 253 }
254
255 inode->i_mode = mode;
256 inode->i_uid = current_fsuid();
257 inode->i_gid = current_fsgid();
258 inode->i_blocks = 0;
259 inode->i_rdev = 0;
260 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
261 inode->i_mapping->a_ops = &v9fs_addr_operations;
262
263 switch (mode & S_IFMT) {
264 case S_IFIFO:
265 case S_IFBLK:
266 case S_IFCHR:
267 case S_IFSOCK:
268 if (!v9fs_extended(v9ses)) {
269 P9_DPRINTK(P9_DEBUG_ERROR,
270 "special files without extended mode\n");
271 err = -EINVAL;
272 goto error;
273 }
274 init_special_inode(inode, inode->i_mode, inode->i_rdev);
275 break;
276 case S_IFREG:
277 inode->i_op = &v9fs_file_inode_operations;
278 inode->i_fop = &v9fs_file_operations;
279 break;
280 case S_IFLNK:
281 if (!v9fs_extended(v9ses)) {
282 P9_DPRINTK(P9_DEBUG_ERROR,
283 "extended modes used w/o 9P2000.u\n");
284 err = -EINVAL;
285 goto error;
286 }
287 inode->i_op = &v9fs_symlink_inode_operations;
288 break;
289 case S_IFDIR:
290 inc_nlink(inode);
291 if (v9fs_extended(v9ses))
292 inode->i_op = &v9fs_dir_inode_operations_ext;
293 else
294 inode->i_op = &v9fs_dir_inode_operations;
295 inode->i_fop = &v9fs_dir_operations;
296 break;
297 default:
298 P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
299 mode, mode & S_IFMT);
300 err = -EINVAL;
301 goto error;
302 }
303
268 return inode; 304 return inode;
305
306error:
307 iput(inode);
308 return ERR_PTR(err);
269} 309}
270 310
271/* 311/*
@@ -320,6 +360,21 @@ error:
320} 360}
321*/ 361*/
322 362
363
364/**
365 * v9fs_clear_inode - release an inode
366 * @inode: inode to release
367 *
368 */
369void v9fs_clear_inode(struct inode *inode)
370{
371 filemap_fdatawrite(inode->i_mapping);
372
373#ifdef CONFIG_9P_FSCACHE
374 v9fs_cache_inode_put_cookie(inode);
375#endif
376}
377
323/** 378/**
324 * v9fs_inode_from_fid - populate an inode by issuing a attribute request 379 * v9fs_inode_from_fid - populate an inode by issuing a attribute request
325 * @v9ses: session information 380 * @v9ses: session information
@@ -338,30 +393,31 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
338 393
339 ret = NULL; 394 ret = NULL;
340 st = p9_client_stat(fid); 395 st = p9_client_stat(fid);
341 if (IS_ERR(st)) { 396 if (IS_ERR(st))
342 err = PTR_ERR(st); 397 return ERR_CAST(st);
343 st = NULL;
344 goto error;
345 }
346 398
347 umode = p9mode2unixmode(v9ses, st->mode); 399 umode = p9mode2unixmode(v9ses, st->mode);
348 ret = v9fs_get_inode(sb, umode); 400 ret = v9fs_get_inode(sb, umode);
349 if (IS_ERR(ret)) { 401 if (IS_ERR(ret)) {
350 err = PTR_ERR(ret); 402 err = PTR_ERR(ret);
351 ret = NULL;
352 goto error; 403 goto error;
353 } 404 }
354 405
355 v9fs_stat2inode(st, ret, sb); 406 v9fs_stat2inode(st, ret, sb);
356 ret->i_ino = v9fs_qid2ino(&st->qid); 407 ret->i_ino = v9fs_qid2ino(&st->qid);
408
409#ifdef CONFIG_9P_FSCACHE
410 v9fs_vcookie_set_qid(ret, &st->qid);
411 v9fs_cache_inode_get_cookie(ret);
412#endif
413 p9stat_free(st);
357 kfree(st); 414 kfree(st);
415
358 return ret; 416 return ret;
359 417
360error: 418error:
419 p9stat_free(st);
361 kfree(st); 420 kfree(st);
362 if (ret)
363 iput(ret);
364
365 return ERR_PTR(err); 421 return ERR_PTR(err);
366} 422}
367 423
@@ -403,9 +459,9 @@ v9fs_open_created(struct inode *inode, struct file *file)
403 * @v9ses: session information 459 * @v9ses: session information
404 * @dir: directory that dentry is being created in 460 * @dir: directory that dentry is being created in
405 * @dentry: dentry that is being created 461 * @dentry: dentry that is being created
462 * @extension: 9p2000.u extension string to support devices, etc.
406 * @perm: create permissions 463 * @perm: create permissions
407 * @mode: open mode 464 * @mode: open mode
408 * @extension: 9p2000.u extension string to support devices, etc.
409 * 465 *
410 */ 466 */
411static struct p9_fid * 467static struct p9_fid *
@@ -470,7 +526,10 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
470 dentry->d_op = &v9fs_dentry_operations; 526 dentry->d_op = &v9fs_dentry_operations;
471 527
472 d_instantiate(dentry, inode); 528 d_instantiate(dentry, inode);
473 v9fs_fid_add(dentry, fid); 529 err = v9fs_fid_add(dentry, fid);
530 if (err < 0)
531 goto error;
532
474 return ofid; 533 return ofid;
475 534
476error: 535error:
@@ -747,7 +806,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
747 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 806 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
748 err = -EPERM; 807 err = -EPERM;
749 v9ses = v9fs_inode2v9ses(dentry->d_inode); 808 v9ses = v9fs_inode2v9ses(dentry->d_inode);
750 if (v9ses->cache == CACHE_LOOSE) 809 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
751 return simple_getattr(mnt, dentry, stat); 810 return simple_getattr(mnt, dentry, stat);
752 811
753 fid = v9fs_fid_lookup(dentry); 812 fid = v9fs_fid_lookup(dentry);
@@ -868,10 +927,10 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
868 } else 927 } else
869 inode->i_rdev = 0; 928 inode->i_rdev = 0;
870 929
871 inode->i_size = stat->length; 930 i_size_write(inode, stat->length);
872 931
873 /* not real number of blocks, but 512 byte ones ... */ 932 /* not real number of blocks, but 512 byte ones ... */
874 inode->i_blocks = (inode->i_size + 512 - 1) >> 9; 933 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
875} 934}
876 935
877/** 936/**