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

Configure Feed

Select the types of activity you want to include in your feed.

nfsd: change nfs4_client_to_reclaim() to allocate data

The calling convention for nfs4_client_to_reclaim() is clumsy in that
the caller needs to free memory if the function fails. It is much
cleaner if the function frees its own memory.

This patch changes nfs4_client_to_reclaim() to re-allocate the .data
fields to be stored in the newly allocated struct nfs4_client_reclaim,
and to free everything on failure.

__cld_pipe_inprogress_downcall() needs to allocate the data anyway to
copy it from user-space, so now that data is allocated twice. I think
that is a small price to pay for a cleaner interface.

Signed-off-by: NeilBrown <neil@brown.name>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

NeilBrown and committed by
Chuck Lever
4552f4e3 89bd77cf

+42 -47
+23 -44
fs/nfsd/nfs4recover.c
··· 147 147 148 148 static void 149 149 __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp, 150 - const char *dname, int len, struct nfsd_net *nn) 150 + char *dname, struct nfsd_net *nn) 151 151 { 152 - struct xdr_netobj name; 152 + struct xdr_netobj name = { .len = strlen(dname), .data = dname }; 153 153 struct xdr_netobj princhash = { .len = 0, .data = NULL }; 154 154 struct nfs4_client_reclaim *crp; 155 155 156 - name.data = kmemdup(dname, len, GFP_KERNEL); 157 - if (!name.data) { 158 - dprintk("%s: failed to allocate memory for name.data!\n", 159 - __func__); 160 - return; 161 - } 162 - name.len = len; 163 156 crp = nfs4_client_to_reclaim(name, princhash, nn); 164 - if (!crp) { 165 - kfree(name.data); 166 - return; 167 - } 168 157 crp->cr_clp = clp; 169 158 } 170 159 ··· 212 223 inode_unlock(d_inode(dir)); 213 224 if (status == 0) { 214 225 if (nn->in_grace) 215 - __nfsd4_create_reclaim_record_grace(clp, dname, 216 - HEXDIR_LEN, nn); 226 + __nfsd4_create_reclaim_record_grace(clp, dname, nn); 217 227 vfs_fsync(nn->rec_file, 0); 218 228 } else { 219 229 printk(KERN_ERR "NFSD: failed to write recovery record" ··· 449 461 static int 450 462 load_recdir(struct dentry *parent, char *cname, struct nfsd_net *nn) 451 463 { 452 - struct xdr_netobj name; 464 + struct xdr_netobj name = { .len = HEXDIR_LEN, .data = cname }; 453 465 struct xdr_netobj princhash = { .len = 0, .data = NULL }; 454 466 455 467 if (strlen(cname) != HEXDIR_LEN - 1) { ··· 458 470 /* Keep trying; maybe the others are OK: */ 459 471 return 0; 460 472 } 461 - name.data = kstrdup(cname, GFP_KERNEL); 462 - if (!name.data) { 463 - dprintk("%s: failed to allocate memory for name.data!\n", 464 - __func__); 465 - goto out; 466 - } 467 - name.len = HEXDIR_LEN; 468 - if (!nfs4_client_to_reclaim(name, princhash, nn)) 469 - kfree(name.data); 470 - out: 473 + nfs4_client_to_reclaim(name, princhash, nn); 471 474 return 0; 472 475 } 473 476 ··· 756 777 { 757 778 uint8_t cmd, princhashlen; 758 779 struct xdr_netobj name, princhash = { .len = 0, .data = NULL }; 780 + char *namecopy __free(kfree) = NULL; 781 + char *princhashcopy __free(kfree) = NULL; 759 782 uint16_t namelen; 760 783 761 784 if (get_user(cmd, &cmsg->cm_cmd)) { ··· 775 794 dprintk("%s: invalid namelen (%u)", __func__, namelen); 776 795 return -EINVAL; 777 796 } 778 - name.data = memdup_user(&ci->cc_name.cn_id, namelen); 779 - if (IS_ERR(name.data)) 780 - return PTR_ERR(name.data); 797 + namecopy = memdup_user(&ci->cc_name.cn_id, namelen); 798 + if (IS_ERR(namecopy)) 799 + return PTR_ERR(namecopy); 800 + name.data = namecopy; 781 801 name.len = namelen; 782 802 get_user(princhashlen, &ci->cc_princhash.cp_len); 783 803 if (princhashlen > 0) { 784 - princhash.data = memdup_user( 785 - &ci->cc_princhash.cp_data, 786 - princhashlen); 787 - if (IS_ERR(princhash.data)) { 788 - kfree(name.data); 789 - return PTR_ERR(princhash.data); 790 - } 804 + princhashcopy = memdup_user( 805 + &ci->cc_princhash.cp_data, 806 + princhashlen); 807 + if (IS_ERR(princhashcopy)) 808 + return PTR_ERR(princhashcopy); 809 + princhash.data = princhashcopy; 791 810 princhash.len = princhashlen; 792 811 } else 793 812 princhash.len = 0; ··· 801 820 dprintk("%s: invalid namelen (%u)", __func__, namelen); 802 821 return -EINVAL; 803 822 } 804 - name.data = memdup_user(&cnm->cn_id, namelen); 805 - if (IS_ERR(name.data)) 806 - return PTR_ERR(name.data); 823 + namecopy = memdup_user(&cnm->cn_id, namelen); 824 + if (IS_ERR(namecopy)) 825 + return PTR_ERR(namecopy); 826 + name.data = namecopy; 807 827 name.len = namelen; 808 828 } 809 829 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING ··· 812 830 struct cld_net *cn = nn->cld_net; 813 831 814 832 name.len = name.len - 5; 815 - memmove(name.data, name.data + 5, name.len); 833 + name.data = name.data + 5; 816 834 cn->cn_has_legacy = true; 817 835 } 818 836 #endif 819 - if (!nfs4_client_to_reclaim(name, princhash, nn)) { 820 - kfree(name.data); 821 - kfree(princhash.data); 837 + if (!nfs4_client_to_reclaim(name, princhash, nn)) 822 838 return -EFAULT; 823 - } 824 839 return nn->client_tracking_ops->msglen; 825 840 } 826 841 return -EFAULT;
+19 -3
fs/nfsd/nfs4state.c
··· 8801 8801 8802 8802 /* 8803 8803 * failure => all reset bets are off, nfserr_no_grace... 8804 - * 8805 - * The caller is responsible for freeing name.data if NULL is returned (it 8806 - * will be freed in nfs4_remove_reclaim_record in the normal case). 8807 8804 */ 8808 8805 struct nfs4_client_reclaim * 8809 8806 nfs4_client_to_reclaim(struct xdr_netobj name, struct xdr_netobj princhash, ··· 8809 8812 unsigned int strhashval; 8810 8813 struct nfs4_client_reclaim *crp; 8811 8814 8815 + name.data = kmemdup(name.data, name.len, GFP_KERNEL); 8816 + if (!name.data) { 8817 + dprintk("%s: failed to allocate memory for name.data!\n", 8818 + __func__); 8819 + return NULL; 8820 + } 8821 + if (princhash.len) { 8822 + princhash.data = kmemdup(princhash.data, princhash.len, GFP_KERNEL); 8823 + if (!princhash.data) { 8824 + dprintk("%s: failed to allocate memory for princhash.data!\n", 8825 + __func__); 8826 + kfree(name.data); 8827 + return NULL; 8828 + } 8829 + } else 8830 + princhash.data = NULL; 8812 8831 crp = alloc_reclaim(); 8813 8832 if (crp) { 8814 8833 strhashval = clientstr_hashval(name); ··· 8836 8823 crp->cr_princhash.len = princhash.len; 8837 8824 crp->cr_clp = NULL; 8838 8825 nn->reclaim_str_hashtbl_size++; 8826 + } else { 8827 + kfree(name.data); 8828 + kfree(princhash.data); 8839 8829 } 8840 8830 return crp; 8841 8831 }