Merge branch 'for-2.6.34' of git://linux-nfs.org/~bfields/linux

* 'for-2.6.34' of git://linux-nfs.org/~bfields/linux: (22 commits)
nfsd4: fix minor memory leak
svcrpc: treat uid's as unsigned
nfsd: ensure sockets are closed on error
Revert "sunrpc: move the close processing after do recvfrom method"
Revert "sunrpc: fix peername failed on closed listener"
sunrpc: remove unnecessary svc_xprt_put
NFSD: NFSv4 callback client should use RPC_TASK_SOFTCONN
xfs_export_operations.commit_metadata
commit_metadata export operation replacing nfsd_sync_dir
lockd: don't clear sm_monitored on nsm_reboot_lookup
lockd: release reference to nsm_handle in nlm_host_rebooted
nfsd: Use vfs_fsync_range() in nfsd_commit
NFSD: Create PF_INET6 listener in write_ports
SUNRPC: NFS kernel APIs shouldn't return ENOENT for "transport not found"
SUNRPC: Bury "#ifdef IPV6" in svc_create_xprt()
NFSD: Support AF_INET6 in svc_addsock() function
SUNRPC: Use rpc_pton() in ip_map_parse()
nfsd: 4.1 has an rfc number
nfsd41: Create the recovery entry for the NFSv4.1 client
nfsd: use vfs_fsync for non-directories
...

+174 -145
+2 -3
Documentation/filesystems/nfs/nfs41-server.txt
··· 17 17 on or off; rpc.nfsd does this correctly.) 18 18 19 19 The NFSv4 minorversion 1 (NFSv4.1) implementation in nfsd is based 20 - on the latest NFSv4.1 Internet Draft: 21 - http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-29 20 + on RFC 5661. 22 21 23 22 From the many new features in NFSv4.1 the current implementation 24 23 focuses on the mandatory-to-implement NFSv4.1 Sessions, providing ··· 43 44 trunking, but this is a mandatory feature, and its use is 44 45 recommended to clients in a number of places. (E.g. to ensure 45 46 timely renewal in case an existing connection's retry timeouts 46 - have gotten too long; see section 8.3 of the draft.) 47 + have gotten too long; see section 8.3 of the RFC.) 47 48 Therefore, lack of this feature may cause future clients to 48 49 fail. 49 50 - Incomplete backchannel support: incomplete backchannel gss
+1 -1
fs/lockd/host.c
··· 479 479 } 480 480 } 481 481 } 482 - 483 482 mutex_unlock(&nlm_host_mutex); 483 + nsm_release(nsm); 484 484 } 485 485 486 486 /*
+3 -9
fs/lockd/mon.c
··· 349 349 * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle 350 350 * @info: pointer to NLMPROC_SM_NOTIFY arguments 351 351 * 352 - * Returns a matching nsm_handle if found in the nsm cache; the returned 353 - * nsm_handle's reference count is bumped and sm_monitored is cleared. 354 - * Otherwise returns NULL if some error occurred. 352 + * Returns a matching nsm_handle if found in the nsm cache. The returned 353 + * nsm_handle's reference count is bumped. Otherwise returns NULL if some 354 + * error occurred. 355 355 */ 356 356 struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info) 357 357 { ··· 369 369 370 370 atomic_inc(&cached->sm_count); 371 371 spin_unlock(&nsm_lock); 372 - 373 - /* 374 - * During subsequent lock activity, force a fresh 375 - * notification to be set up for this host. 376 - */ 377 - cached->sm_monitored = 0; 378 372 379 373 dprintk("lockd: host %s (%s) rebooted, cnt %d\n", 380 374 cached->sm_name, cached->sm_addrbuf,
-2
fs/lockd/svc.c
··· 243 243 if (err < 0) 244 244 goto out_err; 245 245 246 - #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 247 246 err = create_lockd_family(serv, PF_INET6); 248 247 if (err < 0 && err != -EAFNOSUPPORT) 249 248 goto out_err; 250 - #endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ 251 249 252 250 warned = 0; 253 251 return 0;
-2
fs/nfs/callback.c
··· 118 118 dprintk("NFS: Callback listener port = %u (af %u)\n", 119 119 nfs_callback_tcpport, PF_INET); 120 120 121 - #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 122 121 ret = svc_create_xprt(serv, "tcp", PF_INET6, 123 122 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 124 123 if (ret > 0) { ··· 128 129 ret = 0; 129 130 else 130 131 goto out_err; 131 - #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 132 132 133 133 return svc_prepare_thread(serv, &serv->sv_pools[0]); 134 134
+4 -1
fs/nfsd/nfs4callback.c
··· 525 525 526 526 int set_callback_cred(void) 527 527 { 528 + if (callback_cred) 529 + return 0; 528 530 callback_cred = rpc_lookup_machine_cred(); 529 531 if (!callback_cred) 530 532 return -ENOMEM; ··· 544 542 }; 545 543 int status; 546 544 547 - status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT, 545 + status = rpc_call_async(cb->cb_client, &msg, 546 + RPC_TASK_SOFT | RPC_TASK_SOFTCONN, 548 547 &nfsd4_cb_probe_ops, (void *)clp); 549 548 if (status) { 550 549 warn_no_callback_path(clp, status);
+1 -3
fs/nfsd/nfs4recover.c
··· 119 119 static void 120 120 nfsd4_sync_rec_dir(void) 121 121 { 122 - mutex_lock(&rec_dir.dentry->d_inode->i_mutex); 123 - nfsd_sync_dir(rec_dir.dentry); 124 - mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); 122 + vfs_fsync(NULL, rec_dir.dentry, 0); 125 123 } 126 124 127 125 int
+3 -1
fs/nfsd/nfs4state.c
··· 2482 2482 } 2483 2483 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t)); 2484 2484 2485 - if (nfsd4_has_session(&resp->cstate)) 2485 + if (nfsd4_has_session(&resp->cstate)) { 2486 2486 open->op_stateowner->so_confirmed = 1; 2487 + nfsd4_create_clid_dir(open->op_stateowner->so_client); 2488 + } 2487 2489 2488 2490 /* 2489 2491 * Attempt to hand out a delegation. No error return, because the
+1 -1
fs/nfsd/nfs4xdr.c
··· 1434 1434 } 1435 1435 op->opnum = ntohl(*argp->p++); 1436 1436 1437 - if (op->opnum >= OP_ACCESS && op->opnum < ops->nops) 1437 + if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP) 1438 1438 op->status = ops->decoders[op->opnum](argp, &op->u); 1439 1439 else { 1440 1440 op->opnum = OP_ILLEGAL;
+18 -6
fs/nfsd/nfsctl.c
··· 988 988 static ssize_t __write_ports_addxprt(char *buf) 989 989 { 990 990 char transport[16]; 991 + struct svc_xprt *xprt; 991 992 int port, err; 992 993 993 994 if (sscanf(buf, "%15s %4u", transport, &port) != 2) ··· 1003 1002 1004 1003 err = svc_create_xprt(nfsd_serv, transport, 1005 1004 PF_INET, port, SVC_SOCK_ANONYMOUS); 1006 - if (err < 0) { 1007 - /* Give a reasonable perror msg for bad transport string */ 1008 - if (err == -ENOENT) 1009 - err = -EPROTONOSUPPORT; 1010 - return err; 1011 - } 1005 + if (err < 0) 1006 + goto out_err; 1007 + 1008 + err = svc_create_xprt(nfsd_serv, transport, 1009 + PF_INET6, port, SVC_SOCK_ANONYMOUS); 1010 + if (err < 0 && err != -EAFNOSUPPORT) 1011 + goto out_close; 1012 1012 return 0; 1013 + out_close: 1014 + xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port); 1015 + if (xprt != NULL) { 1016 + svc_close_xprt(xprt); 1017 + svc_xprt_put(xprt); 1018 + } 1019 + out_err: 1020 + /* Decrease the count, but don't shut down the service */ 1021 + nfsd_serv->sv_nrthreads--; 1022 + return err; 1013 1023 } 1014 1024 1015 1025 /*
+73 -80
fs/nfsd/vfs.c
··· 26 26 #include <linux/jhash.h> 27 27 #include <linux/ima.h> 28 28 #include <asm/uaccess.h> 29 + #include <linux/exportfs.h> 30 + #include <linux/writeback.h> 29 31 30 32 #ifdef CONFIG_NFSD_V3 31 33 #include "xdr3.h" ··· 272 270 return err; 273 271 } 274 272 273 + /* 274 + * Commit metadata changes to stable storage. 275 + */ 276 + static int 277 + commit_metadata(struct svc_fh *fhp) 278 + { 279 + struct inode *inode = fhp->fh_dentry->d_inode; 280 + const struct export_operations *export_ops = inode->i_sb->s_export_op; 281 + int error = 0; 282 + 283 + if (!EX_ISSYNC(fhp->fh_export)) 284 + return 0; 285 + 286 + if (export_ops->commit_metadata) { 287 + error = export_ops->commit_metadata(inode); 288 + } else { 289 + struct writeback_control wbc = { 290 + .sync_mode = WB_SYNC_ALL, 291 + .nr_to_write = 0, /* metadata only */ 292 + }; 293 + 294 + error = sync_inode(inode, &wbc); 295 + } 296 + 297 + return error; 298 + } 275 299 276 300 /* 277 301 * Set various file attributes. ··· 795 767 } 796 768 797 769 /* 798 - * Sync a file 799 - * As this calls fsync (not fdatasync) there is no need for a write_inode 800 - * after it. 801 - */ 802 - static inline int nfsd_dosync(struct file *filp, struct dentry *dp, 803 - const struct file_operations *fop) 804 - { 805 - struct inode *inode = dp->d_inode; 806 - int (*fsync) (struct file *, struct dentry *, int); 807 - int err; 808 - 809 - err = filemap_write_and_wait(inode->i_mapping); 810 - if (err == 0 && fop && (fsync = fop->fsync)) 811 - err = fsync(filp, dp, 0); 812 - return err; 813 - } 814 - 815 - static int 816 - nfsd_sync(struct file *filp) 817 - { 818 - int err; 819 - struct inode *inode = filp->f_path.dentry->d_inode; 820 - dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name); 821 - mutex_lock(&inode->i_mutex); 822 - err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op); 823 - mutex_unlock(&inode->i_mutex); 824 - 825 - return err; 826 - } 827 - 828 - int 829 - nfsd_sync_dir(struct dentry *dp) 830 - { 831 - return nfsd_dosync(NULL, dp, dp->d_inode->i_fop); 832 - } 833 - 834 - /* 835 770 * Obtain the readahead parameters for the file 836 771 * specified by (dev, ino). 837 772 */ ··· 997 1006 998 1007 if (inode->i_state & I_DIRTY) { 999 1008 dprintk("nfsd: write sync %d\n", task_pid_nr(current)); 1000 - err = nfsd_sync(file); 1009 + err = vfs_fsync(file, file->f_path.dentry, 0); 1001 1010 } 1002 1011 last_ino = inode->i_ino; 1003 1012 last_dev = inode->i_sb->s_dev; ··· 1145 1154 #ifdef CONFIG_NFSD_V3 1146 1155 /* 1147 1156 * Commit all pending writes to stable storage. 1148 - * Strictly speaking, we could sync just the indicated file region here, 1149 - * but there's currently no way we can ask the VFS to do so. 1157 + * 1158 + * Note: we only guarantee that data that lies within the range specified 1159 + * by the 'offset' and 'count' parameters will be synced. 1150 1160 * 1151 1161 * Unfortunately we cannot lock the file to make sure we return full WCC 1152 1162 * data to the client, as locking happens lower down in the filesystem. ··· 1157 1165 loff_t offset, unsigned long count) 1158 1166 { 1159 1167 struct file *file; 1160 - __be32 err; 1168 + loff_t end = LLONG_MAX; 1169 + __be32 err = nfserr_inval; 1161 1170 1162 - if ((u64)count > ~(u64)offset) 1163 - return nfserr_inval; 1171 + if (offset < 0) 1172 + goto out; 1173 + if (count != 0) { 1174 + end = offset + (loff_t)count - 1; 1175 + if (end < offset) 1176 + goto out; 1177 + } 1164 1178 1165 1179 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); 1166 1180 if (err) 1167 - return err; 1181 + goto out; 1168 1182 if (EX_ISSYNC(fhp->fh_export)) { 1169 - if (file->f_op && file->f_op->fsync) { 1170 - err = nfserrno(nfsd_sync(file)); 1171 - } else { 1183 + int err2 = vfs_fsync_range(file, file->f_path.dentry, 1184 + offset, end, 0); 1185 + 1186 + if (err2 != -EINVAL) 1187 + err = nfserrno(err2); 1188 + else 1172 1189 err = nfserr_notsupp; 1173 - } 1174 1190 } 1175 1191 1176 1192 nfsd_close(file); 1193 + out: 1177 1194 return err; 1178 1195 } 1179 1196 #endif /* CONFIG_NFSD_V3 */ ··· 1335 1334 goto out_nfserr; 1336 1335 } 1337 1336 1338 - if (EX_ISSYNC(fhp->fh_export)) { 1339 - err = nfserrno(nfsd_sync_dir(dentry)); 1340 - write_inode_now(dchild->d_inode, 1); 1341 - } 1337 + err = nfsd_create_setattr(rqstp, resfhp, iap); 1342 1338 1343 - err2 = nfsd_create_setattr(rqstp, resfhp, iap); 1339 + /* 1340 + * nfsd_setattr already committed the child. Transactional filesystems 1341 + * had a chance to commit changes for both parent and child 1342 + * simultaneously making the following commit_metadata a noop. 1343 + */ 1344 + err2 = nfserrno(commit_metadata(fhp)); 1344 1345 if (err2) 1345 1346 err = err2; 1346 1347 mnt_drop_write(fhp->fh_export->ex_path.mnt); ··· 1374 1371 struct dentry *dentry, *dchild = NULL; 1375 1372 struct inode *dirp; 1376 1373 __be32 err; 1377 - __be32 err2; 1378 1374 int host_err; 1379 1375 __u32 v_mtime=0, v_atime=0; 1380 1376 ··· 1468 1466 if (created) 1469 1467 *created = 1; 1470 1468 1471 - if (EX_ISSYNC(fhp->fh_export)) { 1472 - err = nfserrno(nfsd_sync_dir(dentry)); 1473 - /* setattr will sync the child (or not) */ 1474 - } 1475 - 1476 1469 nfsd_check_ignore_resizing(iap); 1477 1470 1478 1471 if (createmode == NFS3_CREATE_EXCLUSIVE) { ··· 1482 1485 } 1483 1486 1484 1487 set_attr: 1485 - err2 = nfsd_create_setattr(rqstp, resfhp, iap); 1486 - if (err2) 1487 - err = err2; 1488 + err = nfsd_create_setattr(rqstp, resfhp, iap); 1489 + 1490 + /* 1491 + * nfsd_setattr already committed the child (and possibly also the parent). 1492 + */ 1493 + if (!err) 1494 + err = nfserrno(commit_metadata(fhp)); 1488 1495 1489 1496 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1490 1497 /* ··· 1603 1602 } 1604 1603 } else 1605 1604 host_err = vfs_symlink(dentry->d_inode, dnew, path); 1606 - 1607 - if (!host_err) { 1608 - if (EX_ISSYNC(fhp->fh_export)) 1609 - host_err = nfsd_sync_dir(dentry); 1610 - } 1611 1605 err = nfserrno(host_err); 1606 + if (!err) 1607 + err = nfserrno(commit_metadata(fhp)); 1612 1608 fh_unlock(fhp); 1613 1609 1614 1610 mnt_drop_write(fhp->fh_export->ex_path.mnt); ··· 1667 1669 } 1668 1670 host_err = vfs_link(dold, dirp, dnew); 1669 1671 if (!host_err) { 1670 - if (EX_ISSYNC(ffhp->fh_export)) { 1671 - err = nfserrno(nfsd_sync_dir(ddir)); 1672 - write_inode_now(dest, 1); 1673 - } 1674 - err = 0; 1672 + err = nfserrno(commit_metadata(ffhp)); 1673 + if (!err) 1674 + err = nfserrno(commit_metadata(tfhp)); 1675 1675 } else { 1676 1676 if (host_err == -EXDEV && rqstp->rq_vers == 2) 1677 1677 err = nfserr_acces; ··· 1765 1769 goto out_dput_new; 1766 1770 1767 1771 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1768 - if (!host_err && EX_ISSYNC(tfhp->fh_export)) { 1769 - host_err = nfsd_sync_dir(tdentry); 1772 + if (!host_err) { 1773 + host_err = commit_metadata(tfhp); 1770 1774 if (!host_err) 1771 - host_err = nfsd_sync_dir(fdentry); 1775 + host_err = commit_metadata(ffhp); 1772 1776 } 1773 1777 1774 1778 mnt_drop_write(ffhp->fh_export->ex_path.mnt); ··· 1849 1853 1850 1854 dput(rdentry); 1851 1855 1852 - if (host_err) 1853 - goto out_drop; 1854 - if (EX_ISSYNC(fhp->fh_export)) 1855 - host_err = nfsd_sync_dir(dentry); 1856 + if (!host_err) 1857 + host_err = commit_metadata(fhp); 1856 1858 1857 - out_drop: 1858 1859 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1859 1860 out_nfserr: 1860 1861 err = nfserrno(host_err);
+20
fs/xfs/linux-2.6/xfs_export.c
··· 29 29 #include "xfs_vnodeops.h" 30 30 #include "xfs_bmap_btree.h" 31 31 #include "xfs_inode.h" 32 + #include "xfs_inode_item.h" 32 33 33 34 /* 34 35 * Note that we only accept fileids which are long enough rather than allow ··· 216 215 return d_obtain_alias(VFS_I(cip)); 217 216 } 218 217 218 + STATIC int 219 + xfs_fs_nfs_commit_metadata( 220 + struct inode *inode) 221 + { 222 + struct xfs_inode *ip = XFS_I(inode); 223 + struct xfs_mount *mp = ip->i_mount; 224 + int error = 0; 225 + 226 + xfs_ilock(ip, XFS_ILOCK_SHARED); 227 + if (xfs_ipincount(ip)) { 228 + error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn, 229 + XFS_LOG_SYNC, NULL); 230 + } 231 + xfs_iunlock(ip, XFS_ILOCK_SHARED); 232 + 233 + return error; 234 + } 235 + 219 236 const struct export_operations xfs_export_operations = { 220 237 .encode_fh = xfs_fs_encode_fh, 221 238 .fh_to_dentry = xfs_fs_fh_to_dentry, 222 239 .fh_to_parent = xfs_fs_fh_to_parent, 223 240 .get_parent = xfs_fs_get_parent, 241 + .commit_metadata = xfs_fs_nfs_commit_metadata, 224 242 };
+5
include/linux/exportfs.h
··· 96 96 * @fh_to_parent: find the implied object's parent and get a dentry for it 97 97 * @get_name: find the name for a given inode in a given directory 98 98 * @get_parent: find the parent of a given directory 99 + * @commit_metadata: commit metadata changes to stable storage 99 100 * 100 101 * See Documentation/filesystems/nfs/Exporting for details on how to use 101 102 * this interface correctly. ··· 138 137 * is also a directory. In the event that it cannot be found, or storage 139 138 * space cannot be allocated, a %ERR_PTR should be returned. 140 139 * 140 + * commit_metadata: 141 + * @commit_metadata should commit metadata changes to stable storage. 142 + * 141 143 * Locking rules: 142 144 * get_parent is called with child->d_inode->i_mutex down 143 145 * get_name is not (which is possibly inconsistent) ··· 156 152 int (*get_name)(struct dentry *parent, char *name, 157 153 struct dentry *child); 158 154 struct dentry * (*get_parent)(struct dentry *child); 155 + int (*commit_metadata)(struct inode *inode); 159 156 }; 160 157 161 158 extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
+14 -13
net/sunrpc/svc_xprt.c
··· 173 173 .sin_addr.s_addr = htonl(INADDR_ANY), 174 174 .sin_port = htons(port), 175 175 }; 176 + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 176 177 struct sockaddr_in6 sin6 = { 177 178 .sin6_family = AF_INET6, 178 179 .sin6_addr = IN6ADDR_ANY_INIT, 179 180 .sin6_port = htons(port), 180 181 }; 182 + #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 181 183 struct sockaddr *sap; 182 184 size_t len; 183 185 ··· 188 186 sap = (struct sockaddr *)&sin; 189 187 len = sizeof(sin); 190 188 break; 189 + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 191 190 case PF_INET6: 192 191 sap = (struct sockaddr *)&sin6; 193 192 len = sizeof(sin6); 194 193 break; 194 + #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 195 195 default: 196 196 return ERR_PTR(-EAFNOSUPPORT); 197 197 } ··· 235 231 err: 236 232 spin_unlock(&svc_xprt_class_lock); 237 233 dprintk("svc: transport %s not found\n", xprt_name); 238 - return -ENOENT; 234 + 235 + /* This errno is exposed to user space. Provide a reasonable 236 + * perror msg for a bad transport. */ 237 + return -EPROTONOSUPPORT; 239 238 } 240 239 EXPORT_SYMBOL_GPL(svc_create_xprt); 241 240 ··· 706 699 spin_unlock_bh(&pool->sp_lock); 707 700 708 701 len = 0; 709 - if (test_bit(XPT_LISTENER, &xprt->xpt_flags) && 710 - !test_bit(XPT_CLOSE, &xprt->xpt_flags)) { 702 + if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { 703 + dprintk("svc_recv: found XPT_CLOSE\n"); 704 + svc_delete_xprt(xprt); 705 + } else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { 711 706 struct svc_xprt *newxpt; 712 707 newxpt = xprt->xpt_ops->xpo_accept(xprt); 713 708 if (newxpt) { ··· 735 726 svc_xprt_received(newxpt); 736 727 } 737 728 svc_xprt_received(xprt); 738 - } else if (!test_bit(XPT_CLOSE, &xprt->xpt_flags)) { 729 + } else { 739 730 dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", 740 731 rqstp, pool->sp_id, xprt, 741 732 atomic_read(&xprt->xpt_ref.refcount)); ··· 746 737 } else 747 738 len = xprt->xpt_ops->xpo_recvfrom(rqstp); 748 739 dprintk("svc: got len=%d\n", len); 749 - } 750 - 751 - if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { 752 - dprintk("svc_recv: found XPT_CLOSE\n"); 753 - svc_delete_xprt(xprt); 754 740 } 755 741 756 742 /* No data, incomplete (TCP) read, or accept() */ ··· 893 889 if (test_bit(XPT_TEMP, &xprt->xpt_flags)) 894 890 serv->sv_tmpcnt--; 895 891 896 - for (dr = svc_deferred_dequeue(xprt); dr; 897 - dr = svc_deferred_dequeue(xprt)) { 898 - svc_xprt_put(xprt); 892 + while ((dr = svc_deferred_dequeue(xprt)) != NULL) 899 893 kfree(dr); 900 - } 901 894 902 895 svc_xprt_put(xprt); 903 896 spin_unlock_bh(&serv->sv_lock);
+27 -22
net/sunrpc/svcauth_unix.c
··· 15 15 #include <linux/kernel.h> 16 16 #define RPCDBG_FACILITY RPCDBG_AUTH 17 17 18 + #include <linux/sunrpc/clnt.h> 18 19 19 20 /* 20 21 * AUTHUNIX and AUTHNULL credentials are both handled here. ··· 188 187 * for scratch: */ 189 188 char *buf = mesg; 190 189 int len; 191 - int b1, b2, b3, b4, b5, b6, b7, b8; 192 - char c; 193 190 char class[8]; 194 - struct in6_addr addr; 191 + union { 192 + struct sockaddr sa; 193 + struct sockaddr_in s4; 194 + struct sockaddr_in6 s6; 195 + } address; 196 + struct sockaddr_in6 sin6; 195 197 int err; 196 198 197 199 struct ip_map *ipmp; ··· 213 209 len = qword_get(&mesg, buf, mlen); 214 210 if (len <= 0) return -EINVAL; 215 211 216 - if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) == 4) { 217 - addr.s6_addr32[0] = 0; 218 - addr.s6_addr32[1] = 0; 219 - addr.s6_addr32[2] = htonl(0xffff); 220 - addr.s6_addr32[3] = 221 - htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); 222 - } else if (sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%c", 223 - &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) { 224 - addr.s6_addr16[0] = htons(b1); 225 - addr.s6_addr16[1] = htons(b2); 226 - addr.s6_addr16[2] = htons(b3); 227 - addr.s6_addr16[3] = htons(b4); 228 - addr.s6_addr16[4] = htons(b5); 229 - addr.s6_addr16[5] = htons(b6); 230 - addr.s6_addr16[6] = htons(b7); 231 - addr.s6_addr16[7] = htons(b8); 232 - } else 212 + if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0) 233 213 return -EINVAL; 214 + switch (address.sa.sa_family) { 215 + case AF_INET: 216 + /* Form a mapped IPv4 address in sin6 */ 217 + memset(&sin6, 0, sizeof(sin6)); 218 + sin6.sin6_family = AF_INET6; 219 + sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); 220 + sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr; 221 + break; 222 + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 223 + case AF_INET6: 224 + memcpy(&sin6, &address.s6, sizeof(sin6)); 225 + break; 226 + #endif 227 + default: 228 + return -EINVAL; 229 + } 234 230 235 231 expiry = get_expiry(&mesg); 236 232 if (expiry ==0) ··· 247 243 } else 248 244 dom = NULL; 249 245 250 - ipmp = ip_map_lookup(class, &addr); 246 + /* IPv6 scope IDs are ignored for now */ 247 + ipmp = ip_map_lookup(class, &sin6.sin6_addr); 251 248 if (ipmp) { 252 249 err = ip_map_update(ipmp, 253 250 container_of(dom, struct unix_domain, h), ··· 624 619 else 625 620 glen = 0; 626 621 627 - seq_printf(m, "%d %d:", ug->uid, glen); 622 + seq_printf(m, "%u %d:", ug->uid, glen); 628 623 for (i = 0; i < glen; i++) 629 624 seq_printf(m, " %d", GROUP_AT(ug->gi, i)); 630 625 seq_printf(m, "\n");
+2 -1
net/sunrpc/svcsock.c
··· 968 968 return len; 969 969 err_delete: 970 970 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); 971 + svc_xprt_received(&svsk->sk_xprt); 971 972 err_again: 972 973 return -EAGAIN; 973 974 } ··· 1358 1357 1359 1358 if (!so) 1360 1359 return err; 1361 - if (so->sk->sk_family != AF_INET) 1360 + if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) 1362 1361 err = -EAFNOSUPPORT; 1363 1362 else if (so->sk->sk_protocol != IPPROTO_TCP && 1364 1363 so->sk->sk_protocol != IPPROTO_UDP)