diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 95 |
1 files changed, 61 insertions, 34 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 0c13fc600049..2b696ae6655a 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -307,7 +307,7 @@ v9fs_create(struct inode *dir, | |||
307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
308 | struct super_block *sb = dir->i_sb; | 308 | struct super_block *sb = dir->i_sb; |
309 | struct v9fs_fid *dirfid = | 309 | struct v9fs_fid *dirfid = |
310 | v9fs_fid_lookup(file_dentry->d_parent, FID_WALK); | 310 | v9fs_fid_lookup(file_dentry->d_parent); |
311 | struct v9fs_fid *fid = NULL; | 311 | struct v9fs_fid *fid = NULL; |
312 | struct inode *file_inode = NULL; | 312 | struct inode *file_inode = NULL; |
313 | struct v9fs_fcall *fcall = NULL; | 313 | struct v9fs_fcall *fcall = NULL; |
@@ -317,6 +317,7 @@ v9fs_create(struct inode *dir, | |||
317 | long newfid = -1; | 317 | long newfid = -1; |
318 | int result = 0; | 318 | int result = 0; |
319 | unsigned int iounit = 0; | 319 | unsigned int iounit = 0; |
320 | int wfidno = -1; | ||
320 | 321 | ||
321 | perm = unixmode2p9mode(v9ses, perm); | 322 | perm = unixmode2p9mode(v9ses, perm); |
322 | 323 | ||
@@ -350,7 +351,7 @@ v9fs_create(struct inode *dir, | |||
350 | if (result < 0) { | 351 | if (result < 0) { |
351 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | 352 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); |
352 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 353 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
353 | newfid = 0; | 354 | newfid = -1; |
354 | goto CleanUpFid; | 355 | goto CleanUpFid; |
355 | } | 356 | } |
356 | 357 | ||
@@ -369,20 +370,39 @@ v9fs_create(struct inode *dir, | |||
369 | qid = fcall->params.rcreate.qid; | 370 | qid = fcall->params.rcreate.qid; |
370 | kfree(fcall); | 371 | kfree(fcall); |
371 | 372 | ||
372 | fid = v9fs_fid_create(file_dentry); | 373 | fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); |
374 | dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); | ||
373 | if (!fid) { | 375 | if (!fid) { |
374 | result = -ENOMEM; | 376 | result = -ENOMEM; |
375 | goto CleanUpFid; | 377 | goto CleanUpFid; |
376 | } | 378 | } |
377 | 379 | ||
378 | fid->fid = newfid; | ||
379 | fid->fidopen = 0; | ||
380 | fid->fidcreate = 1; | ||
381 | fid->qid = qid; | 380 | fid->qid = qid; |
382 | fid->iounit = iounit; | 381 | fid->iounit = iounit; |
383 | fid->rdir_pos = 0; | 382 | |
384 | fid->rdir_fcall = NULL; | 383 | /* walk to the newly created file and put the fid in the dentry */ |
385 | fid->v9ses = v9ses; | 384 | wfidno = v9fs_get_idpool(&v9ses->fidpool); |
385 | if (newfid < 0) { | ||
386 | eprintk(KERN_WARNING, "no free fids available\n"); | ||
387 | return -ENOSPC; | ||
388 | } | ||
389 | |||
390 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, | ||
391 | (char *) file_dentry->d_name.name, NULL); | ||
392 | if (result < 0) { | ||
393 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | ||
394 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
395 | wfidno = -1; | ||
396 | goto CleanUpFid; | ||
397 | } | ||
398 | |||
399 | if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { | ||
400 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) { | ||
401 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
402 | } | ||
403 | |||
404 | goto CleanUpFid; | ||
405 | } | ||
386 | 406 | ||
387 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || | 407 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || |
388 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || | 408 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || |
@@ -410,11 +430,11 @@ v9fs_create(struct inode *dir, | |||
410 | d_instantiate(file_dentry, file_inode); | 430 | d_instantiate(file_dentry, file_inode); |
411 | 431 | ||
412 | if (perm & V9FS_DMDIR) { | 432 | if (perm & V9FS_DMDIR) { |
413 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 433 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
435 | else | ||
414 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", | 436 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", |
415 | FCALL_ERROR(fcall)); | 437 | FCALL_ERROR(fcall)); |
416 | |||
417 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
418 | kfree(fcall); | 438 | kfree(fcall); |
419 | fid->fidopen = 0; | 439 | fid->fidopen = 0; |
420 | fid->fidcreate = 0; | 440 | fid->fidcreate = 0; |
@@ -426,12 +446,22 @@ v9fs_create(struct inode *dir, | |||
426 | CleanUpFid: | 446 | CleanUpFid: |
427 | kfree(fcall); | 447 | kfree(fcall); |
428 | 448 | ||
429 | if (newfid) { | 449 | if (newfid >= 0) { |
430 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 450 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
451 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
452 | else | ||
453 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | ||
454 | FCALL_ERROR(fcall)); | ||
455 | |||
456 | kfree(fcall); | ||
457 | } | ||
458 | if (wfidno >= 0) { | ||
459 | if (!v9fs_t_clunk(v9ses, wfidno, &fcall)) | ||
460 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
461 | else | ||
431 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | 462 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", |
432 | FCALL_ERROR(fcall)); | 463 | FCALL_ERROR(fcall)); |
433 | 464 | ||
434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
435 | kfree(fcall); | 465 | kfree(fcall); |
436 | } | 466 | } |
437 | return result; | 467 | return result; |
@@ -461,7 +491,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
461 | file_inode = file->d_inode; | 491 | file_inode = file->d_inode; |
462 | sb = file_inode->i_sb; | 492 | sb = file_inode->i_sb; |
463 | v9ses = v9fs_inode2v9ses(file_inode); | 493 | v9ses = v9fs_inode2v9ses(file_inode); |
464 | v9fid = v9fs_fid_lookup(file, FID_OP); | 494 | v9fid = v9fs_fid_lookup(file); |
465 | 495 | ||
466 | if (!v9fid) { | 496 | if (!v9fid) { |
467 | dprintk(DEBUG_ERROR, | 497 | dprintk(DEBUG_ERROR, |
@@ -545,7 +575,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
545 | 575 | ||
546 | sb = dir->i_sb; | 576 | sb = dir->i_sb; |
547 | v9ses = v9fs_inode2v9ses(dir); | 577 | v9ses = v9fs_inode2v9ses(dir); |
548 | dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); | 578 | dirfid = v9fs_fid_lookup(dentry->d_parent); |
549 | 579 | ||
550 | if (!dirfid) { | 580 | if (!dirfid) { |
551 | dprintk(DEBUG_ERROR, "no dirfid\n"); | 581 | dprintk(DEBUG_ERROR, "no dirfid\n"); |
@@ -573,7 +603,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
573 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 603 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
574 | if (result == -ENOENT) { | 604 | if (result == -ENOENT) { |
575 | d_add(dentry, NULL); | 605 | d_add(dentry, NULL); |
576 | dprintk(DEBUG_ERROR, | 606 | dprintk(DEBUG_VFS, |
577 | "Return negative dentry %p count %d\n", | 607 | "Return negative dentry %p count %d\n", |
578 | dentry, atomic_read(&dentry->d_count)); | 608 | dentry, atomic_read(&dentry->d_count)); |
579 | return NULL; | 609 | return NULL; |
@@ -601,16 +631,13 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
601 | 631 | ||
602 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 632 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); |
603 | 633 | ||
604 | fid = v9fs_fid_create(dentry); | 634 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); |
605 | if (fid == NULL) { | 635 | if (fid == NULL) { |
606 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | 636 | dprintk(DEBUG_ERROR, "couldn't insert\n"); |
607 | result = -ENOMEM; | 637 | result = -ENOMEM; |
608 | goto FreeFcall; | 638 | goto FreeFcall; |
609 | } | 639 | } |
610 | 640 | ||
611 | fid->fid = newfid; | ||
612 | fid->fidopen = 0; | ||
613 | fid->v9ses = v9ses; | ||
614 | fid->qid = fcall->params.rstat.stat->qid; | 641 | fid->qid = fcall->params.rstat.stat->qid; |
615 | 642 | ||
616 | dentry->d_op = &v9fs_dentry_operations; | 643 | dentry->d_op = &v9fs_dentry_operations; |
@@ -665,11 +692,11 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
665 | { | 692 | { |
666 | struct inode *old_inode = old_dentry->d_inode; | 693 | struct inode *old_inode = old_dentry->d_inode; |
667 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); | 694 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); |
668 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK); | 695 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
669 | struct v9fs_fid *olddirfid = | 696 | struct v9fs_fid *olddirfid = |
670 | v9fs_fid_lookup(old_dentry->d_parent, FID_WALK); | 697 | v9fs_fid_lookup(old_dentry->d_parent); |
671 | struct v9fs_fid *newdirfid = | 698 | struct v9fs_fid *newdirfid = |
672 | v9fs_fid_lookup(new_dentry->d_parent, FID_WALK); | 699 | v9fs_fid_lookup(new_dentry->d_parent); |
673 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 700 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
674 | struct v9fs_fcall *fcall = NULL; | 701 | struct v9fs_fcall *fcall = NULL; |
675 | int fid = -1; | 702 | int fid = -1; |
@@ -744,7 +771,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
744 | { | 771 | { |
745 | struct v9fs_fcall *fcall = NULL; | 772 | struct v9fs_fcall *fcall = NULL; |
746 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 773 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
747 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 774 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
748 | int err = -EPERM; | 775 | int err = -EPERM; |
749 | 776 | ||
750 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); | 777 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); |
@@ -778,7 +805,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
778 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | 805 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) |
779 | { | 806 | { |
780 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 807 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
781 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 808 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
782 | struct v9fs_fcall *fcall = NULL; | 809 | struct v9fs_fcall *fcall = NULL; |
783 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 810 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
784 | int res = -EPERM; | 811 | int res = -EPERM; |
@@ -960,7 +987,7 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
960 | if (retval != 0) | 987 | if (retval != 0) |
961 | goto FreeFcall; | 988 | goto FreeFcall; |
962 | 989 | ||
963 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 990 | newfid = v9fs_fid_lookup(dentry); |
964 | 991 | ||
965 | /* issue a twstat */ | 992 | /* issue a twstat */ |
966 | v9fs_blank_mistat(v9ses, mistat); | 993 | v9fs_blank_mistat(v9ses, mistat); |
@@ -1004,7 +1031,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
1004 | 1031 | ||
1005 | struct v9fs_fcall *fcall = NULL; | 1032 | struct v9fs_fcall *fcall = NULL; |
1006 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 1033 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
1007 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 1034 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
1008 | 1035 | ||
1009 | if (!fid) { | 1036 | if (!fid) { |
1010 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); | 1037 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); |
@@ -1063,8 +1090,8 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, | |||
1063 | int ret; | 1090 | int ret; |
1064 | char *link = __getname(); | 1091 | char *link = __getname(); |
1065 | 1092 | ||
1066 | if (strlen(link) < buflen) | 1093 | if (buflen > PATH_MAX) |
1067 | buflen = strlen(link); | 1094 | buflen = PATH_MAX; |
1068 | 1095 | ||
1069 | dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 1096 | dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
1070 | 1097 | ||
@@ -1148,7 +1175,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1148 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 1175 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
1149 | struct v9fs_fcall *fcall = NULL; | 1176 | struct v9fs_fcall *fcall = NULL; |
1150 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 1177 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
1151 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP); | 1178 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
1152 | struct v9fs_fid *newfid = NULL; | 1179 | struct v9fs_fid *newfid = NULL; |
1153 | char *symname = __getname(); | 1180 | char *symname = __getname(); |
1154 | 1181 | ||
@@ -1168,7 +1195,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1168 | if (retval != 0) | 1195 | if (retval != 0) |
1169 | goto FreeMem; | 1196 | goto FreeMem; |
1170 | 1197 | ||
1171 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1198 | newfid = v9fs_fid_lookup(dentry); |
1172 | if (!newfid) { | 1199 | if (!newfid) { |
1173 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); | 1200 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); |
1174 | goto FreeMem; | 1201 | goto FreeMem; |
@@ -1246,7 +1273,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1246 | if (retval != 0) | 1273 | if (retval != 0) |
1247 | goto FreeMem; | 1274 | goto FreeMem; |
1248 | 1275 | ||
1249 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1276 | newfid = v9fs_fid_lookup(dentry); |
1250 | if (!newfid) { | 1277 | if (!newfid) { |
1251 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); | 1278 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); |
1252 | retval = -EINVAL; | 1279 | retval = -EINVAL; |