Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag '9p-for-5.11-rc1' of git://github.com/martinetd/linux

Pull 9p update from Dominique Martinet:

- fix long-standing limitation on open-unlink-fop pattern

- add refcount to p9_fid (fixes the above and will allow for more
cleanups and simplifications in the future)

* tag '9p-for-5.11-rc1' of git://github.com/martinetd/linux:
9p: Remove unnecessary IS_ERR() check
9p: Uninitialized variable in v9fs_writeback_fid()
9p: Fix writeback fid incorrectly being attached to dentry
9p: apply review requests for fid refcounting
9p: add refcount to p9_fid struct
fs/9p: search open fids first
fs/9p: track open fids
fs/9p: fix create-unlink-getattr idiom

+178 -33
+60 -5
fs/9p/fid.c
··· 39 39 } 40 40 41 41 /** 42 + * v9fs_fid_find_inode - search for an open fid off of the inode list 43 + * @inode: return a fid pointing to a specific inode 44 + * @uid: return a fid belonging to the specified user 45 + * 46 + */ 47 + 48 + static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid) 49 + { 50 + struct hlist_head *h; 51 + struct p9_fid *fid, *ret = NULL; 52 + 53 + p9_debug(P9_DEBUG_VFS, " inode: %p\n", inode); 54 + 55 + spin_lock(&inode->i_lock); 56 + h = (struct hlist_head *)&inode->i_private; 57 + hlist_for_each_entry(fid, h, ilist) { 58 + if (uid_eq(fid->uid, uid)) { 59 + refcount_inc(&fid->count); 60 + ret = fid; 61 + break; 62 + } 63 + } 64 + spin_unlock(&inode->i_lock); 65 + return ret; 66 + } 67 + 68 + /** 69 + * v9fs_open_fid_add - add an open fid to an inode 70 + * @dentry: inode that the fid is being added to 71 + * @fid: fid to add 72 + * 73 + */ 74 + 75 + void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid) 76 + { 77 + spin_lock(&inode->i_lock); 78 + hlist_add_head(&fid->ilist, (struct hlist_head *)&inode->i_private); 79 + spin_unlock(&inode->i_lock); 80 + } 81 + 82 + 83 + /** 42 84 * v9fs_fid_find - retrieve a fid that belongs to the specified uid 43 85 * @dentry: dentry to look for fid in 44 86 * @uid: return fid that belongs to the specified user ··· 96 54 dentry, dentry, from_kuid(&init_user_ns, uid), 97 55 any); 98 56 ret = NULL; 57 + 58 + if (d_inode(dentry)) 59 + ret = v9fs_fid_find_inode(d_inode(dentry), uid); 60 + 99 61 /* we'll recheck under lock if there's anything to look in */ 100 - if (dentry->d_fsdata) { 62 + if (!ret && dentry->d_fsdata) { 101 63 struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata; 102 64 spin_lock(&dentry->d_lock); 103 65 hlist_for_each_entry(fid, h, dlist) { 104 66 if (any || uid_eq(fid->uid, uid)) { 105 67 ret = fid; 68 + refcount_inc(&ret->count); 106 69 break; 107 70 } 108 71 } ··· 169 122 fid = v9fs_fid_find(ds, uid, any); 170 123 if (fid) { 171 124 /* Found the parent fid do a lookup with that */ 172 - fid = p9_client_walk(fid, 1, &dentry->d_name.name, 1); 125 + struct p9_fid *ofid = fid; 126 + 127 + fid = p9_client_walk(ofid, 1, &dentry->d_name.name, 1); 128 + p9_client_clunk(ofid); 173 129 goto fid_out; 174 130 } 175 131 up_read(&v9ses->rename_sem); ··· 197 147 v9fs_fid_add(dentry->d_sb->s_root, fid); 198 148 } 199 149 /* If we are root ourself just return that */ 200 - if (dentry->d_sb->s_root == dentry) 150 + if (dentry->d_sb->s_root == dentry) { 151 + refcount_inc(&fid->count); 201 152 return fid; 153 + } 202 154 /* 203 155 * Do a multipath walk with attached root. 204 156 * When walking parent we need to make sure we ··· 247 195 fid = ERR_PTR(-ENOENT); 248 196 } else { 249 197 __add_fid(dentry, fid); 198 + refcount_inc(&fid->count); 250 199 spin_unlock(&dentry->d_lock); 251 200 } 252 201 } ··· 298 245 struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) 299 246 { 300 247 int err; 301 - struct p9_fid *fid; 248 + struct p9_fid *fid, *ofid; 302 249 303 - fid = clone_fid(v9fs_fid_lookup_with_uid(dentry, GLOBAL_ROOT_UID, 0)); 250 + ofid = v9fs_fid_lookup_with_uid(dentry, GLOBAL_ROOT_UID, 0); 251 + fid = clone_fid(ofid); 304 252 if (IS_ERR(fid)) 305 253 goto error_out; 254 + p9_client_clunk(ofid); 306 255 /* 307 256 * writeback fid will only be used to write back the 308 257 * dirty pages. We always request for the open fid in read-write
+10 -1
fs/9p/fid.h
··· 15 15 } 16 16 void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid); 17 17 struct p9_fid *v9fs_writeback_fid(struct dentry *dentry); 18 + void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid); 18 19 static inline struct p9_fid *clone_fid(struct p9_fid *fid) 19 20 { 20 21 return IS_ERR(fid) ? fid : p9_client_walk(fid, 0, NULL, 1); 21 22 } 22 23 static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry) 23 24 { 24 - return clone_fid(v9fs_fid_lookup(dentry)); 25 + struct p9_fid *fid, *nfid; 26 + 27 + fid = v9fs_fid_lookup(dentry); 28 + if (!fid || IS_ERR(fid)) 29 + return fid; 30 + 31 + nfid = clone_fid(fid); 32 + p9_client_clunk(fid); 33 + return nfid; 25 34 } 26 35 #endif
+2
fs/9p/vfs_dentry.c
··· 85 85 retval = v9fs_refresh_inode_dotl(fid, inode); 86 86 else 87 87 retval = v9fs_refresh_inode(fid, inode); 88 + p9_client_clunk(fid); 89 + 88 90 if (retval == -ENOENT) 89 91 return 0; 90 92 if (retval < 0)
+5 -1
fs/9p/vfs_dir.c
··· 210 210 fid = filp->private_data; 211 211 p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n", 212 212 inode, filp, fid ? fid->fid : -1); 213 - if (fid) 213 + if (fid) { 214 + spin_lock(&inode->i_lock); 215 + hlist_del(&fid->ilist); 216 + spin_unlock(&inode->i_lock); 214 217 p9_client_clunk(fid); 218 + } 215 219 return 0; 216 220 } 217 221
+4 -3
fs/9p/vfs_file.c
··· 46 46 int err; 47 47 struct v9fs_inode *v9inode; 48 48 struct v9fs_session_info *v9ses; 49 - struct p9_fid *fid; 49 + struct p9_fid *fid, *writeback_fid; 50 50 int omode; 51 51 52 52 p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); ··· 85 85 * because we want write after unlink usecase 86 86 * to work. 87 87 */ 88 - fid = v9fs_writeback_fid(file_dentry(file)); 88 + writeback_fid = v9fs_writeback_fid(file_dentry(file)); 89 89 if (IS_ERR(fid)) { 90 90 err = PTR_ERR(fid); 91 91 mutex_unlock(&v9inode->v_mutex); 92 92 goto out_error; 93 93 } 94 - v9inode->writeback_fid = (void *) fid; 94 + v9inode->writeback_fid = (void *) writeback_fid; 95 95 } 96 96 mutex_unlock(&v9inode->v_mutex); 97 97 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 98 98 v9fs_cache_inode_set_cookie(inode, file); 99 + v9fs_open_fid_add(inode, fid); 99 100 return 0; 100 101 out_error: 101 102 p9_client_clunk(file->private_data);
+38 -9
fs/9p/vfs_inode.c
··· 256 256 inode->i_rdev = rdev; 257 257 inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); 258 258 inode->i_mapping->a_ops = &v9fs_addr_operations; 259 + inode->i_private = NULL; 259 260 260 261 switch (mode & S_IFMT) { 261 262 case S_IFIFO: ··· 551 550 if (v9fs_proto_dotl(v9ses)) 552 551 retval = p9_client_unlinkat(dfid, dentry->d_name.name, 553 552 v9fs_at_to_dotl_flags(flags)); 553 + p9_client_clunk(dfid); 554 554 if (retval == -EOPNOTSUPP) { 555 555 /* Try the one based on path */ 556 556 v9fid = v9fs_fid_clone(dentry); ··· 572 570 573 571 v9fs_invalidate_inode_attr(inode); 574 572 v9fs_invalidate_inode_attr(dir); 573 + 574 + /* invalidate all fids associated with dentry */ 575 + /* NOTE: This will not include open fids */ 576 + dentry->d_op->d_release(dentry); 575 577 } 576 578 return retval; 577 579 } ··· 596 590 { 597 591 int err; 598 592 const unsigned char *name; 599 - struct p9_fid *dfid, *ofid, *fid; 593 + struct p9_fid *dfid, *ofid = NULL, *fid = NULL; 600 594 struct inode *inode; 601 595 602 596 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry); 603 597 604 598 err = 0; 605 - ofid = NULL; 606 - fid = NULL; 607 599 name = dentry->d_name.name; 608 600 dfid = v9fs_parent_fid(dentry); 609 601 if (IS_ERR(dfid)) { ··· 615 611 if (IS_ERR(ofid)) { 616 612 err = PTR_ERR(ofid); 617 613 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 614 + p9_client_clunk(dfid); 618 615 return ERR_PTR(err); 619 616 } 620 617 621 618 err = p9_client_fcreate(ofid, name, perm, mode, extension); 622 619 if (err < 0) { 623 620 p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err); 621 + p9_client_clunk(dfid); 624 622 goto error; 625 623 } 626 624 ··· 634 628 p9_debug(P9_DEBUG_VFS, 635 629 "p9_client_walk failed %d\n", err); 636 630 fid = NULL; 631 + p9_client_clunk(dfid); 637 632 goto error; 638 633 } 639 634 /* ··· 645 638 err = PTR_ERR(inode); 646 639 p9_debug(P9_DEBUG_VFS, 647 640 "inode creation failed %d\n", err); 641 + p9_client_clunk(dfid); 648 642 goto error; 649 643 } 650 644 v9fs_fid_add(dentry, fid); 651 645 d_instantiate(dentry, inode); 652 646 } 647 + p9_client_clunk(dfid); 653 648 return ofid; 654 649 error: 655 650 if (ofid) ··· 764 755 */ 765 756 name = dentry->d_name.name; 766 757 fid = p9_client_walk(dfid, 1, &name, 1); 758 + p9_client_clunk(dfid); 767 759 if (fid == ERR_PTR(-ENOENT)) 768 760 inode = NULL; 769 761 else if (IS_ERR(fid)) ··· 802 792 struct v9fs_session_info *v9ses; 803 793 struct p9_fid *fid, *inode_fid; 804 794 struct dentry *res = NULL; 795 + struct inode *inode; 805 796 806 797 if (d_in_lookup(dentry)) { 807 798 res = v9fs_vfs_lookup(dir, dentry, 0); ··· 831 820 } 832 821 833 822 v9fs_invalidate_inode_attr(dir); 834 - v9inode = V9FS_I(d_inode(dentry)); 823 + inode = d_inode(dentry); 824 + v9inode = V9FS_I(inode); 835 825 mutex_lock(&v9inode->v_mutex); 836 826 if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) && 837 827 !v9inode->writeback_fid && ··· 860 848 file->private_data = fid; 861 849 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 862 850 v9fs_cache_inode_set_cookie(d_inode(dentry), file); 851 + v9fs_open_fid_add(inode, fid); 863 852 864 853 file->f_mode |= FMODE_CREATED; 865 854 out: ··· 915 902 struct inode *old_inode; 916 903 struct inode *new_inode; 917 904 struct v9fs_session_info *v9ses; 918 - struct p9_fid *oldfid; 905 + struct p9_fid *oldfid, *dfid; 919 906 struct p9_fid *olddirfid; 920 907 struct p9_fid *newdirfid; 921 908 struct p9_wstat wstat; ··· 932 919 if (IS_ERR(oldfid)) 933 920 return PTR_ERR(oldfid); 934 921 935 - olddirfid = clone_fid(v9fs_parent_fid(old_dentry)); 922 + dfid = v9fs_parent_fid(old_dentry); 923 + olddirfid = clone_fid(dfid); 924 + if (dfid && !IS_ERR(dfid)) 925 + p9_client_clunk(dfid); 926 + 936 927 if (IS_ERR(olddirfid)) { 937 928 retval = PTR_ERR(olddirfid); 938 929 goto done; 939 930 } 940 931 941 - newdirfid = clone_fid(v9fs_parent_fid(new_dentry)); 932 + dfid = v9fs_parent_fid(new_dentry); 933 + newdirfid = clone_fid(dfid); 934 + p9_client_clunk(dfid); 935 + 942 936 if (IS_ERR(newdirfid)) { 943 937 retval = PTR_ERR(newdirfid); 944 938 goto clunk_olddir; ··· 1002 982 p9_client_clunk(olddirfid); 1003 983 1004 984 done: 985 + p9_client_clunk(oldfid); 1005 986 return retval; 1006 987 } 1007 988 ··· 1035 1014 return PTR_ERR(fid); 1036 1015 1037 1016 st = p9_client_stat(fid); 1017 + p9_client_clunk(fid); 1038 1018 if (IS_ERR(st)) 1039 1019 return PTR_ERR(st); 1040 1020 ··· 1056 1034 1057 1035 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) 1058 1036 { 1059 - int retval; 1037 + int retval, use_dentry = 0; 1060 1038 struct v9fs_session_info *v9ses; 1061 1039 struct p9_fid *fid = NULL; 1062 1040 struct p9_wstat wstat; ··· 1072 1050 fid = iattr->ia_file->private_data; 1073 1051 WARN_ON(!fid); 1074 1052 } 1075 - if (!fid) 1053 + if (!fid) { 1076 1054 fid = v9fs_fid_lookup(dentry); 1055 + use_dentry = 1; 1056 + } 1077 1057 if(IS_ERR(fid)) 1078 1058 return PTR_ERR(fid); 1079 1059 ··· 1105 1081 filemap_write_and_wait(d_inode(dentry)->i_mapping); 1106 1082 1107 1083 retval = p9_client_wstat(fid, &wstat); 1084 + 1085 + if (use_dentry) 1086 + p9_client_clunk(fid); 1087 + 1108 1088 if (retval < 0) 1109 1089 return retval; 1110 1090 ··· 1233 1205 return ERR_PTR(-EBADF); 1234 1206 1235 1207 st = p9_client_stat(fid); 1208 + p9_client_clunk(fid); 1236 1209 if (IS_ERR(st)) 1237 1210 return ERR_CAST(st); 1238 1211
+29 -6
fs/9p/vfs_inode_dotl.c
··· 296 296 297 297 /* instantiate inode and assign the unopened fid to the dentry */ 298 298 fid = p9_client_walk(dfid, 1, &name, 1); 299 + p9_client_clunk(dfid); 299 300 if (IS_ERR(fid)) { 300 301 err = PTR_ERR(fid); 301 302 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); ··· 343 342 file->private_data = ofid; 344 343 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 345 344 v9fs_cache_inode_set_cookie(inode, file); 345 + v9fs_open_fid_add(inode, ofid); 346 346 file->f_mode |= FMODE_CREATED; 347 347 out: 348 348 v9fs_put_acl(dacl, pacl); ··· 409 407 err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); 410 408 if (err < 0) 411 409 goto error; 412 - 413 410 fid = p9_client_walk(dfid, 1, &name, 1); 414 411 if (IS_ERR(fid)) { 415 412 err = PTR_ERR(fid); ··· 452 451 if (fid) 453 452 p9_client_clunk(fid); 454 453 v9fs_put_acl(dacl, pacl); 454 + p9_client_clunk(dfid); 455 455 return err; 456 456 } 457 457 ··· 480 478 */ 481 479 482 480 st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 481 + p9_client_clunk(fid); 483 482 if (IS_ERR(st)) 484 483 return PTR_ERR(st); 485 484 ··· 542 539 543 540 int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) 544 541 { 545 - int retval; 542 + int retval, use_dentry = 0; 546 543 struct p9_fid *fid = NULL; 547 544 struct p9_iattr_dotl p9attr; 548 545 struct inode *inode = d_inode(dentry); ··· 567 564 fid = iattr->ia_file->private_data; 568 565 WARN_ON(!fid); 569 566 } 570 - if (!fid) 567 + if (!fid) { 571 568 fid = v9fs_fid_lookup(dentry); 569 + use_dentry = 1; 570 + } 572 571 if (IS_ERR(fid)) 573 572 return PTR_ERR(fid); 574 573 ··· 579 574 filemap_write_and_wait(inode->i_mapping); 580 575 581 576 retval = p9_client_setattr(fid, &p9attr); 582 - if (retval < 0) 577 + if (retval < 0) { 578 + if (use_dentry) 579 + p9_client_clunk(fid); 583 580 return retval; 581 + } 584 582 585 583 if ((iattr->ia_valid & ATTR_SIZE) && 586 584 iattr->ia_size != i_size_read(inode)) ··· 595 587 if (iattr->ia_valid & ATTR_MODE) { 596 588 /* We also want to update ACL when we update mode bits */ 597 589 retval = v9fs_acl_chmod(inode, fid); 598 - if (retval < 0) 590 + if (retval < 0) { 591 + if (use_dentry) 592 + p9_client_clunk(fid); 599 593 return retval; 594 + } 600 595 } 596 + if (use_dentry) 597 + p9_client_clunk(fid); 598 + 601 599 return 0; 602 600 } 603 601 ··· 755 741 if (fid) 756 742 p9_client_clunk(fid); 757 743 744 + p9_client_clunk(dfid); 758 745 return err; 759 746 } 760 747 ··· 784 769 return PTR_ERR(dfid); 785 770 786 771 oldfid = v9fs_fid_lookup(old_dentry); 787 - if (IS_ERR(oldfid)) 772 + if (IS_ERR(oldfid)) { 773 + p9_client_clunk(dfid); 788 774 return PTR_ERR(oldfid); 775 + } 789 776 790 777 err = p9_client_link(dfid, oldfid, dentry->d_name.name); 791 778 779 + p9_client_clunk(dfid); 780 + p9_client_clunk(oldfid); 792 781 if (err < 0) { 793 782 p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); 794 783 return err; ··· 807 788 return PTR_ERR(fid); 808 789 809 790 v9fs_refresh_inode_dotl(fid, d_inode(old_dentry)); 791 + p9_client_clunk(fid); 810 792 } 811 793 ihold(d_inode(old_dentry)); 812 794 d_instantiate(dentry, d_inode(old_dentry)); ··· 906 886 if (fid) 907 887 p9_client_clunk(fid); 908 888 v9fs_put_acl(dacl, pacl); 889 + p9_client_clunk(dfid); 890 + 909 891 return err; 910 892 } 911 893 ··· 936 914 if (IS_ERR(fid)) 937 915 return ERR_CAST(fid); 938 916 retval = p9_client_readlink(fid, &target); 917 + p9_client_clunk(fid); 939 918 if (retval) 940 919 return ERR_PTR(retval); 941 920 set_delayed_call(done, kfree_link, target);
+1
fs/9p/vfs_super.c
··· 268 268 } 269 269 res = simple_statfs(dentry, buf); 270 270 done: 271 + p9_client_clunk(fid); 271 272 return res; 272 273 } 273 274
+13 -3
fs/9p/xattr.c
··· 71 71 void *buffer, size_t buffer_size) 72 72 { 73 73 struct p9_fid *fid; 74 + int ret; 74 75 75 76 p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu\n", 76 77 name, buffer_size); 77 78 fid = v9fs_fid_lookup(dentry); 78 79 if (IS_ERR(fid)) 79 80 return PTR_ERR(fid); 81 + ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size); 82 + p9_client_clunk(fid); 80 83 81 - return v9fs_fid_xattr_get(fid, name, buffer, buffer_size); 84 + return ret; 82 85 } 83 86 84 87 /* ··· 99 96 int v9fs_xattr_set(struct dentry *dentry, const char *name, 100 97 const void *value, size_t value_len, int flags) 101 98 { 102 - struct p9_fid *fid = v9fs_fid_lookup(dentry); 103 - return v9fs_fid_xattr_set(fid, name, value, value_len, flags); 99 + int ret; 100 + struct p9_fid *fid; 101 + 102 + fid = v9fs_fid_lookup(dentry); 103 + if (IS_ERR(fid)) 104 + return PTR_ERR(fid); 105 + ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags); 106 + p9_client_clunk(fid); 107 + return ret; 104 108 } 105 109 106 110 int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
+7
include/net/9p/client.h
··· 140 140 * 141 141 * TODO: This needs lots of explanation. 142 142 */ 143 + enum fid_source { 144 + FID_FROM_OTHER, 145 + FID_FROM_INODE, 146 + FID_FROM_DENTRY, 147 + }; 143 148 144 149 struct p9_fid { 145 150 struct p9_client *clnt; 146 151 u32 fid; 152 + refcount_t count; 147 153 int mode; 148 154 struct p9_qid qid; 149 155 u32 iounit; ··· 158 152 void *rdir; 159 153 160 154 struct hlist_node dlist; /* list of all fids attached to a dentry */ 155 + struct hlist_node ilist; 161 156 }; 162 157 163 158 /**
+9 -5
net/9p/client.c
··· 903 903 fid->clnt = clnt; 904 904 fid->rdir = NULL; 905 905 fid->fid = 0; 906 + refcount_set(&fid->count, 1); 906 907 907 908 idr_preload(GFP_KERNEL); 908 909 spin_lock_irq(&clnt->lock); ··· 911 910 GFP_NOWAIT); 912 911 spin_unlock_irq(&clnt->lock); 913 912 idr_preload_end(); 914 - 915 913 if (!ret) 916 914 return fid; 917 915 ··· 1189 1189 1190 1190 p9_debug(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n", 1191 1191 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); 1192 - 1193 1192 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, 1194 1193 nwname, wnames); 1195 1194 if (IS_ERR(req)) { ··· 1220 1221 if (nwname) 1221 1222 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid)); 1222 1223 else 1223 - fid->qid = oldfid->qid; 1224 + memmove(&fid->qid, &oldfid->qid, sizeof(struct p9_qid)); 1224 1225 1225 1226 kfree(wqids); 1226 1227 return fid; ··· 1273 1274 p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type, 1274 1275 (unsigned long long)qid.path, qid.version, iounit); 1275 1276 1277 + memmove(&fid->qid, &qid, sizeof(struct p9_qid)); 1276 1278 fid->mode = mode; 1277 1279 fid->iounit = iounit; 1278 1280 ··· 1319 1319 (unsigned long long)qid->path, 1320 1320 qid->version, iounit); 1321 1321 1322 + memmove(&ofid->qid, qid, sizeof(struct p9_qid)); 1322 1323 ofid->mode = mode; 1323 1324 ofid->iounit = iounit; 1324 1325 ··· 1365 1364 (unsigned long long)qid.path, 1366 1365 qid.version, iounit); 1367 1366 1367 + memmove(&fid->qid, &qid, sizeof(struct p9_qid)); 1368 1368 fid->mode = mode; 1369 1369 fid->iounit = iounit; 1370 1370 ··· 1462 1460 struct p9_req_t *req; 1463 1461 int retries = 0; 1464 1462 1465 - if (!fid) { 1466 - pr_warn("%s (%d): Trying to clunk with NULL fid\n", 1463 + if (!fid || IS_ERR(fid)) { 1464 + pr_warn("%s (%d): Trying to clunk with invalid fid\n", 1467 1465 __func__, task_pid_nr(current)); 1468 1466 dump_stack(); 1469 1467 return 0; 1470 1468 } 1469 + if (!refcount_dec_and_test(&fid->count)) 1470 + return 0; 1471 1471 1472 1472 again: 1473 1473 p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid,