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; |
