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

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

Pull nfsd update from J Bruce Fields:
"Another relatively quiet cycle. There was some progress on my
remaining 4.1 todo's, but a couple of them were just of the form
"check that we do X correctly", so didn't have much affect on the
code.

Other than that, a bunch of cleanup and some bugfixes (including an
annoying NFSv4.0 state leak and a busy-loop in the server that could
cause it to peg the CPU without making progress)."

* 'for-3.7' of git://linux-nfs.org/~bfields/linux: (46 commits)
UAPI: (Scripted) Disintegrate include/linux/sunrpc
UAPI: (Scripted) Disintegrate include/linux/nfsd
nfsd4: don't allow reclaims of expired clients
nfsd4: remove redundant callback probe
nfsd4: expire old client earlier
nfsd4: separate session allocation and initialization
nfsd4: clean up session allocation
nfsd4: minor free_session cleanup
nfsd4: new_conn_from_crses should only allocate
nfsd4: separate connection allocation and initialization
nfsd4: reject bad forechannel attrs earlier
nfsd4: enforce per-client sessions/no-sessions distinction
nfsd4: set cl_minorversion at create time
nfsd4: don't pin clientids to pseudoflavors
nfsd4: fix bind_conn_to_session xdr comment
nfsd4: cast readlink() bug argument
NFSD: pass null terminated buf to kstrtouint()
nfsd: remove duplicate init in nfsd4_cb_recall
nfsd4: eliminate redundant nfs4_free_stateid
fs/nfsd/nfs4idmap.c: adjust inconsistent IS_ERR and PTR_ERR
...

+754 -755
+41
Documentation/filesystems/nfs/nfsd-admin-interfaces.txt
··· 1 + Administrative interfaces for nfsd 2 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 3 + 4 + Note that normally these interfaces are used only by the utilities in 5 + nfs-utils. 6 + 7 + nfsd is controlled mainly by pseudofiles under the "nfsd" filesystem, 8 + which is normally mounted at /proc/fs/nfsd/. 9 + 10 + The server is always started by the first write of a nonzero value to 11 + nfsd/threads. 12 + 13 + Before doing that, NFSD can be told which sockets to listen on by 14 + writing to nfsd/portlist; that write may be: 15 + 16 + - an ascii-encoded file descriptor, which should refer to a 17 + bound (and listening, for tcp) socket, or 18 + - "transportname port", where transportname is currently either 19 + "udp", "tcp", or "rdma". 20 + 21 + If nfsd is started without doing any of these, then it will create one 22 + udp and one tcp listener at port 2049 (see nfsd_init_socks). 23 + 24 + On startup, nfsd and lockd grace periods start. 25 + 26 + nfsd is shut down by a write of 0 to nfsd/threads. All locks and state 27 + are thrown away at that point. 28 + 29 + Between startup and shutdown, the number of threads may be adjusted up 30 + or down by additional writes to nfsd/threads or by writes to 31 + nfsd/pool_threads. 32 + 33 + For more detail about files under nfsd/ and what they control, see 34 + fs/nfsd/nfsctl.c; most of them have detailed comments. 35 + 36 + Implementation notes 37 + ^^^^^^^^^^^^^^^^^^^^ 38 + 39 + Note that the rpc server requires the caller to serialize addition and 40 + removal of listening sockets, and startup and shutdown of the server. 41 + For nfsd this is done using nfsd_mutex.
+2 -15
fs/lockd/svc.c
··· 126 126 static int 127 127 lockd(void *vrqstp) 128 128 { 129 - int err = 0, preverr = 0; 129 + int err = 0; 130 130 struct svc_rqst *rqstp = vrqstp; 131 131 132 132 /* try_to_freeze() is called from svc_recv() */ ··· 165 165 * recvfrom routine. 166 166 */ 167 167 err = svc_recv(rqstp, timeout); 168 - if (err == -EAGAIN || err == -EINTR) { 169 - preverr = err; 168 + if (err == -EAGAIN || err == -EINTR) 170 169 continue; 171 - } 172 - if (err < 0) { 173 - if (err != preverr) { 174 - printk(KERN_WARNING "%s: unexpected error " 175 - "from svc_recv (%d)\n", __func__, err); 176 - preverr = err; 177 - } 178 - schedule_timeout_interruptible(HZ); 179 - continue; 180 - } 181 - preverr = err; 182 - 183 170 dprintk("lockd: request from %s\n", 184 171 svc_print_addr(rqstp, buf, sizeof(buf))); 185 172
+3 -3
fs/locks.c
··· 1289 1289 void lease_get_mtime(struct inode *inode, struct timespec *time) 1290 1290 { 1291 1291 struct file_lock *flock = inode->i_flock; 1292 - if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK)) 1292 + if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK)) 1293 1293 *time = current_fs_time(inode->i_sb); 1294 1294 else 1295 1295 *time = inode->i_mtime; ··· 2185 2185 } else { 2186 2186 seq_printf(f, "%s ", 2187 2187 (lease_breaking(fl)) 2188 - ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " 2189 - : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); 2188 + ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ " 2189 + : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ "); 2190 2190 } 2191 2191 if (inode) { 2192 2192 #ifdef WE_CAN_BREAK_LSLK_NOW
+2 -14
fs/nfs/callback.c
··· 72 72 static int 73 73 nfs4_callback_svc(void *vrqstp) 74 74 { 75 - int err, preverr = 0; 75 + int err; 76 76 struct svc_rqst *rqstp = vrqstp; 77 77 78 78 set_freezable(); ··· 82 82 * Listen for a request on the socket 83 83 */ 84 84 err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); 85 - if (err == -EAGAIN || err == -EINTR) { 86 - preverr = err; 85 + if (err == -EAGAIN || err == -EINTR) 87 86 continue; 88 - } 89 - if (err < 0) { 90 - if (err != preverr) { 91 - printk(KERN_WARNING "NFS: %s: unexpected error " 92 - "from svc_recv (%d)\n", __func__, err); 93 - preverr = err; 94 - } 95 - schedule_timeout_uninterruptible(HZ); 96 - continue; 97 - } 98 - preverr = err; 99 87 svc_process(rqstp); 100 88 } 101 89 return 0;
+1 -2
fs/nfsd/nfs2acl.c
··· 218 218 * There must be an encoding function for void results so svc_process 219 219 * will work properly. 220 220 */ 221 - int 222 - nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) 221 + static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) 223 222 { 224 223 return xdr_ressize_check(rqstp, p); 225 224 }
+1 -1
fs/nfsd/nfs3proc.c
··· 247 247 /* Now create the file and set attributes */ 248 248 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, 249 249 attr, newfhp, 250 - argp->createmode, argp->verf, NULL, NULL); 250 + argp->createmode, (u32 *)argp->verf, NULL, NULL); 251 251 252 252 RETURN_STATUS(nfserr); 253 253 }
-1
fs/nfsd/nfs4callback.c
··· 1028 1028 cb->cb_msg.rpc_cred = callback_cred; 1029 1029 1030 1030 cb->cb_ops = &nfsd4_cb_recall_ops; 1031 - dp->dl_retries = 1; 1032 1031 1033 1032 INIT_LIST_HEAD(&cb->cb_per_client); 1034 1033 cb->cb_done = true;
+2 -2
fs/nfsd/nfs4idmap.c
··· 478 478 goto destroy_idtoname_cache; 479 479 nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); 480 480 if (IS_ERR(nn->nametoid_cache)) { 481 - rv = PTR_ERR(nn->idtoname_cache); 481 + rv = PTR_ERR(nn->nametoid_cache); 482 482 goto unregister_idtoname_cache; 483 483 } 484 484 rv = cache_register_net(nn->nametoid_cache, net); ··· 598 598 /* Just to make sure it's null-terminated: */ 599 599 memcpy(buf, name, namelen); 600 600 buf[namelen] = '\0'; 601 - ret = kstrtouint(name, 10, id); 601 + ret = kstrtouint(buf, 10, id); 602 602 return ret == 0; 603 603 } 604 604
+3 -3
fs/nfsd/nfs4proc.c
··· 370 370 break; 371 371 case NFS4_OPEN_CLAIM_PREVIOUS: 372 372 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 373 - status = nfs4_check_open_reclaim(&open->op_clientid); 373 + status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion); 374 374 if (status) 375 375 goto out; 376 376 case NFS4_OPEN_CLAIM_FH: ··· 1054 1054 char *op_name; 1055 1055 /* Try to get response size before operation */ 1056 1056 nfsd4op_rsize op_rsize_bop; 1057 - stateid_setter op_get_currentstateid; 1058 - stateid_getter op_set_currentstateid; 1057 + stateid_getter op_get_currentstateid; 1058 + stateid_setter op_set_currentstateid; 1059 1059 }; 1060 1060 1061 1061 static struct nfsd4_operation nfsd4_ops[];
+194 -153
fs/nfsd/nfs4state.c
··· 758 758 spin_unlock(&nfsd_drc_lock); 759 759 } 760 760 761 - static struct nfsd4_session *alloc_session(int slotsize, int numslots) 761 + static struct nfsd4_session *__alloc_session(int slotsize, int numslots) 762 762 { 763 763 struct nfsd4_session *new; 764 764 int mem, i; ··· 852 852 return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); 853 853 } 854 854 855 - static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) 855 + static void nfsd4_init_conn(struct svc_rqst *rqstp, struct nfsd4_conn *conn, struct nfsd4_session *ses) 856 856 { 857 - struct nfsd4_conn *conn; 858 857 int ret; 859 858 860 - conn = alloc_conn(rqstp, dir); 861 - if (!conn) 862 - return nfserr_jukebox; 863 859 nfsd4_hash_conn(conn, ses); 864 860 ret = nfsd4_register_conn(conn); 865 861 if (ret) 866 862 /* oops; xprt is already down: */ 867 863 nfsd4_conn_lost(&conn->cn_xpt_user); 868 - if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN && 869 - dir & NFS4_CDFC4_BACK) { 864 + if (conn->cn_flags & NFS4_CDFC4_BACK) { 870 865 /* callback channel may be back up */ 871 866 nfsd4_probe_callback(ses->se_client); 872 867 } 873 - return nfs_ok; 874 868 } 875 869 876 - static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) 870 + static struct nfsd4_conn *alloc_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_create_session *cses) 877 871 { 878 872 u32 dir = NFS4_CDFC4_FORE; 879 873 880 - if (ses->se_flags & SESSION4_BACK_CHAN) 874 + if (cses->flags & SESSION4_BACK_CHAN) 881 875 dir |= NFS4_CDFC4_BACK; 882 - 883 - return nfsd4_new_conn(rqstp, ses, dir); 876 + return alloc_conn(rqstp, dir); 884 877 } 885 878 886 879 /* must be called under client_lock */ ··· 896 903 spin_unlock(&clp->cl_lock); 897 904 } 898 905 906 + static void __free_session(struct nfsd4_session *ses) 907 + { 908 + nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs); 909 + free_session_slots(ses); 910 + kfree(ses); 911 + } 912 + 899 913 static void free_session(struct kref *kref) 900 914 { 901 915 struct nfsd4_session *ses; 902 - int mem; 903 916 904 917 lockdep_assert_held(&client_lock); 905 918 ses = container_of(kref, struct nfsd4_session, se_ref); 906 919 nfsd4_del_conns(ses); 907 - spin_lock(&nfsd_drc_lock); 908 - mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel); 909 - nfsd_drc_mem_used -= mem; 910 - spin_unlock(&nfsd_drc_lock); 911 - free_session_slots(ses); 912 - kfree(ses); 920 + __free_session(ses); 913 921 } 914 922 915 923 void nfsd4_put_session(struct nfsd4_session *ses) ··· 920 926 spin_unlock(&client_lock); 921 927 } 922 928 923 - static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) 929 + static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan) 924 930 { 925 931 struct nfsd4_session *new; 926 - struct nfsd4_channel_attrs *fchan = &cses->fore_channel; 927 932 int numslots, slotsize; 928 - __be32 status; 929 - int idx; 930 - 931 933 /* 932 934 * Note decreasing slot size below client's request may 933 935 * make it difficult for client to function correctly, whereas ··· 936 946 if (numslots < 1) 937 947 return NULL; 938 948 939 - new = alloc_session(slotsize, numslots); 949 + new = __alloc_session(slotsize, numslots); 940 950 if (!new) { 941 951 nfsd4_put_drc_mem(slotsize, fchan->maxreqs); 942 952 return NULL; 943 953 } 944 954 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); 955 + return new; 956 + } 957 + 958 + static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses) 959 + { 960 + int idx; 945 961 946 962 new->se_client = clp; 947 963 gen_sessionid(new); ··· 966 970 spin_unlock(&clp->cl_lock); 967 971 spin_unlock(&client_lock); 968 972 969 - status = nfsd4_new_conn_from_crses(rqstp, new); 970 - /* whoops: benny points out, status is ignored! (err, or bogus) */ 971 - if (status) { 972 - spin_lock(&client_lock); 973 - free_session(&new->se_ref); 974 - spin_unlock(&client_lock); 975 - return NULL; 976 - } 977 973 if (cses->flags & SESSION4_BACK_CHAN) { 978 974 struct sockaddr *sa = svc_addr(rqstp); 979 975 /* ··· 978 990 rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); 979 991 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); 980 992 } 981 - nfsd4_probe_callback(clp); 982 993 return new; 983 994 } 984 995 ··· 1118 1131 } 1119 1132 1120 1133 static void 1121 - expire_client(struct nfs4_client *clp) 1134 + destroy_client(struct nfs4_client *clp) 1122 1135 { 1123 1136 struct nfs4_openowner *oo; 1124 1137 struct nfs4_delegation *dp; ··· 1150 1163 if (atomic_read(&clp->cl_refcount) == 0) 1151 1164 free_client(clp); 1152 1165 spin_unlock(&client_lock); 1166 + } 1167 + 1168 + static void expire_client(struct nfs4_client *clp) 1169 + { 1170 + nfsd4_client_record_remove(clp); 1171 + destroy_client(clp); 1153 1172 } 1154 1173 1155 1174 static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) ··· 1216 1223 return true; 1217 1224 } 1218 1225 1226 + /* 1227 + * RFC 3530 language requires clid_inuse be returned when the 1228 + * "principal" associated with a requests differs from that previously 1229 + * used. We use uid, gid's, and gss principal string as our best 1230 + * approximation. We also don't want to allow non-gss use of a client 1231 + * established using gss: in theory cr_principal should catch that 1232 + * change, but in practice cr_principal can be null even in the gss case 1233 + * since gssd doesn't always pass down a principal string. 1234 + */ 1235 + static bool is_gss_cred(struct svc_cred *cr) 1236 + { 1237 + /* Is cr_flavor one of the gss "pseudoflavors"?: */ 1238 + return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR); 1239 + } 1240 + 1241 + 1219 1242 static bool 1220 1243 same_creds(struct svc_cred *cr1, struct svc_cred *cr2) 1221 1244 { 1222 - if ((cr1->cr_flavor != cr2->cr_flavor) 1245 + if ((is_gss_cred(cr1) != is_gss_cred(cr2)) 1223 1246 || (cr1->cr_uid != cr2->cr_uid) 1224 1247 || (cr1->cr_gid != cr2->cr_gid) 1225 1248 || !groups_equal(cr1->cr_group_info, cr2->cr_group_info)) ··· 1349 1340 } 1350 1341 1351 1342 static struct nfs4_client * 1352 - find_confirmed_client(clientid_t *clid) 1343 + find_confirmed_client(clientid_t *clid, bool sessions) 1353 1344 { 1354 1345 struct nfs4_client *clp; 1355 1346 unsigned int idhashval = clientid_hashval(clid->cl_id); 1356 1347 1357 1348 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { 1358 1349 if (same_clid(&clp->cl_clientid, clid)) { 1350 + if ((bool)clp->cl_minorversion != sessions) 1351 + return NULL; 1359 1352 renew_client(clp); 1360 1353 return clp; 1361 1354 } ··· 1366 1355 } 1367 1356 1368 1357 static struct nfs4_client * 1369 - find_unconfirmed_client(clientid_t *clid) 1358 + find_unconfirmed_client(clientid_t *clid, bool sessions) 1370 1359 { 1371 1360 struct nfs4_client *clp; 1372 1361 unsigned int idhashval = clientid_hashval(clid->cl_id); 1373 1362 1374 1363 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { 1375 - if (same_clid(&clp->cl_clientid, clid)) 1364 + if (same_clid(&clp->cl_clientid, clid)) { 1365 + if ((bool)clp->cl_minorversion != sessions) 1366 + return NULL; 1376 1367 return clp; 1368 + } 1377 1369 } 1378 1370 return NULL; 1379 1371 } ··· 1665 1651 status = nfserr_jukebox; 1666 1652 goto out; 1667 1653 } 1654 + new->cl_minorversion = 1; 1668 1655 1669 1656 gen_clid(new); 1670 1657 add_to_unconfirmed(new, strhashval); ··· 1758 1743 struct sockaddr *sa = svc_addr(rqstp); 1759 1744 struct nfs4_client *conf, *unconf; 1760 1745 struct nfsd4_session *new; 1746 + struct nfsd4_conn *conn; 1761 1747 struct nfsd4_clid_slot *cs_slot = NULL; 1762 - bool confirm_me = false; 1763 1748 __be32 status = 0; 1764 1749 1765 1750 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) 1766 1751 return nfserr_inval; 1752 + if (check_forechannel_attrs(cr_ses->fore_channel)) 1753 + return nfserr_toosmall; 1754 + new = alloc_session(&cr_ses->fore_channel); 1755 + if (!new) 1756 + return nfserr_jukebox; 1757 + status = nfserr_jukebox; 1758 + conn = alloc_conn_from_crses(rqstp, cr_ses); 1759 + if (!conn) 1760 + goto out_free_session; 1767 1761 1768 1762 nfs4_lock_state(); 1769 - unconf = find_unconfirmed_client(&cr_ses->clientid); 1770 - conf = find_confirmed_client(&cr_ses->clientid); 1763 + unconf = find_unconfirmed_client(&cr_ses->clientid, true); 1764 + conf = find_confirmed_client(&cr_ses->clientid, true); 1771 1765 1772 1766 if (conf) { 1773 1767 cs_slot = &conf->cl_cs_slot; 1774 1768 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1775 1769 if (status == nfserr_replay_cache) { 1776 1770 status = nfsd4_replay_create_session(cr_ses, cs_slot); 1777 - goto out; 1771 + goto out_free_conn; 1778 1772 } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) { 1779 1773 status = nfserr_seq_misordered; 1780 - goto out; 1774 + goto out_free_conn; 1781 1775 } 1782 1776 } else if (unconf) { 1777 + unsigned int hash; 1778 + struct nfs4_client *old; 1783 1779 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || 1784 1780 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { 1785 1781 status = nfserr_clid_inuse; 1786 - goto out; 1782 + goto out_free_conn; 1787 1783 } 1788 1784 cs_slot = &unconf->cl_cs_slot; 1789 1785 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1790 1786 if (status) { 1791 1787 /* an unconfirmed replay returns misordered */ 1792 1788 status = nfserr_seq_misordered; 1793 - goto out; 1789 + goto out_free_conn; 1794 1790 } 1795 - confirm_me = true; 1791 + hash = clientstr_hashval(unconf->cl_recdir); 1792 + old = find_confirmed_client_by_str(unconf->cl_recdir, hash); 1793 + if (old) 1794 + expire_client(old); 1795 + move_to_confirmed(unconf); 1796 1796 conf = unconf; 1797 1797 } else { 1798 1798 status = nfserr_stale_clientid; 1799 - goto out; 1799 + goto out_free_conn; 1800 1800 } 1801 - 1802 - /* 1803 - * XXX: we should probably set this at creation time, and check 1804 - * for consistent minorversion use throughout: 1805 - */ 1806 - conf->cl_minorversion = 1; 1801 + status = nfs_ok; 1807 1802 /* 1808 1803 * We do not support RDMA or persistent sessions 1809 1804 */ 1810 1805 cr_ses->flags &= ~SESSION4_PERSIST; 1811 1806 cr_ses->flags &= ~SESSION4_RDMA; 1812 1807 1813 - status = nfserr_toosmall; 1814 - if (check_forechannel_attrs(cr_ses->fore_channel)) 1815 - goto out; 1808 + init_session(rqstp, new, conf, cr_ses); 1809 + nfsd4_init_conn(rqstp, conn, new); 1816 1810 1817 - status = nfserr_jukebox; 1818 - new = alloc_init_session(rqstp, conf, cr_ses); 1819 - if (!new) 1820 - goto out; 1821 - status = nfs_ok; 1822 1811 memcpy(cr_ses->sessionid.data, new->se_sessionid.data, 1823 1812 NFS4_MAX_SESSIONID_LEN); 1824 1813 memcpy(&cr_ses->fore_channel, &new->se_fchannel, ··· 1832 1813 1833 1814 /* cache solo and embedded create sessions under the state lock */ 1834 1815 nfsd4_cache_create_session(cr_ses, cs_slot, status); 1835 - if (confirm_me) { 1836 - unsigned int hash = clientstr_hashval(unconf->cl_recdir); 1837 - struct nfs4_client *old = 1838 - find_confirmed_client_by_str(conf->cl_recdir, hash); 1839 - if (old) 1840 - expire_client(old); 1841 - move_to_confirmed(conf); 1842 - } 1843 1816 out: 1844 1817 nfs4_unlock_state(); 1845 1818 dprintk("%s returns %d\n", __func__, ntohl(status)); 1846 1819 return status; 1820 + out_free_conn: 1821 + free_conn(conn); 1822 + out_free_session: 1823 + __free_session(new); 1824 + goto out; 1847 1825 } 1848 1826 1849 1827 static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) ··· 1870 1854 struct nfsd4_bind_conn_to_session *bcts) 1871 1855 { 1872 1856 __be32 status; 1857 + struct nfsd4_conn *conn; 1873 1858 1874 1859 if (!nfsd4_last_compound_op(rqstp)) 1875 1860 return nfserr_not_only_op; ··· 1887 1870 return nfserr_badsession; 1888 1871 1889 1872 status = nfsd4_map_bcts_dir(&bcts->dir); 1890 - if (!status) 1891 - nfsd4_new_conn(rqstp, cstate->session, bcts->dir); 1892 - return status; 1873 + if (status) 1874 + return status; 1875 + conn = alloc_conn(rqstp, bcts->dir); 1876 + if (!conn) 1877 + return nfserr_jukebox; 1878 + nfsd4_init_conn(rqstp, conn, cstate->session); 1879 + return nfs_ok; 1893 1880 } 1894 1881 1895 1882 static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) ··· 2106 2085 __be32 status = 0; 2107 2086 2108 2087 nfs4_lock_state(); 2109 - unconf = find_unconfirmed_client(&dc->clientid); 2110 - conf = find_confirmed_client(&dc->clientid); 2088 + unconf = find_unconfirmed_client(&dc->clientid, true); 2089 + conf = find_confirmed_client(&dc->clientid, true); 2111 2090 2112 2091 if (conf) { 2113 2092 clp = conf; ··· 2221 2200 copy_clid(new, conf); 2222 2201 else /* case 4 (new client) or cases 2, 3 (client reboot): */ 2223 2202 gen_clid(new); 2224 - /* 2225 - * XXX: we should probably set this at creation time, and check 2226 - * for consistent minorversion use throughout: 2227 - */ 2228 2203 new->cl_minorversion = 0; 2229 2204 gen_callback(new, setclid, rqstp); 2230 2205 add_to_unconfirmed(new, strhashval); ··· 2249 2232 return nfserr_stale_clientid; 2250 2233 nfs4_lock_state(); 2251 2234 2252 - conf = find_confirmed_client(clid); 2253 - unconf = find_unconfirmed_client(clid); 2235 + conf = find_confirmed_client(clid, false); 2236 + unconf = find_unconfirmed_client(clid, false); 2254 2237 /* 2255 2238 * We try hard to give out unique clientid's, so if we get an 2256 2239 * attempt to confirm the same clientid with a different cred, ··· 2279 2262 unsigned int hash = clientstr_hashval(unconf->cl_recdir); 2280 2263 2281 2264 conf = find_confirmed_client_by_str(unconf->cl_recdir, hash); 2282 - if (conf) { 2283 - nfsd4_client_record_remove(conf); 2265 + if (conf) 2284 2266 expire_client(conf); 2285 - } 2286 2267 move_to_confirmed(unconf); 2287 2268 nfsd4_probe_callback(unconf); 2288 2269 } ··· 2462 2447 } 2463 2448 2464 2449 static struct nfs4_openowner * 2465 - find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) 2450 + find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions) 2466 2451 { 2467 2452 struct nfs4_stateowner *so; 2468 2453 struct nfs4_openowner *oo; 2454 + struct nfs4_client *clp; 2469 2455 2470 2456 list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { 2471 2457 if (!so->so_is_open_owner) 2472 2458 continue; 2473 2459 if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { 2474 2460 oo = openowner(so); 2461 + clp = oo->oo_owner.so_client; 2462 + if ((bool)clp->cl_minorversion != sessions) 2463 + return NULL; 2475 2464 renew_client(oo->oo_owner.so_client); 2476 2465 return oo; 2477 2466 } ··· 2619 2600 return nfserr_jukebox; 2620 2601 2621 2602 strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); 2622 - oo = find_openstateowner_str(strhashval, open); 2603 + oo = find_openstateowner_str(strhashval, open, cstate->minorversion); 2623 2604 open->op_openowner = oo; 2624 2605 if (!oo) { 2625 - clp = find_confirmed_client(clientid); 2606 + clp = find_confirmed_client(clientid, cstate->minorversion); 2626 2607 if (clp == NULL) 2627 2608 return nfserr_expired; 2628 2609 goto new_owner; ··· 2722 2703 return nfserr_share_denied; 2723 2704 } 2724 2705 return nfs_ok; 2725 - } 2726 - 2727 - static void nfs4_free_stateid(struct nfs4_ol_stateid *s) 2728 - { 2729 - kmem_cache_free(stateid_slab, s); 2730 2706 } 2731 2707 2732 2708 static inline int nfs4_access_to_access(u32 nfs4_access) ··· 3101 3087 if (open->op_file) 3102 3088 nfsd4_free_file(open->op_file); 3103 3089 if (open->op_stp) 3104 - nfs4_free_stateid(open->op_stp); 3090 + free_generic_stateid(open->op_stp); 3105 3091 } 3106 3092 3107 3093 __be32 ··· 3118 3104 status = nfserr_stale_clientid; 3119 3105 if (STALE_CLIENTID(clid, nn)) 3120 3106 goto out; 3121 - clp = find_confirmed_client(clid); 3107 + clp = find_confirmed_client(clid, cstate->minorversion); 3122 3108 status = nfserr_expired; 3123 3109 if (clp == NULL) { 3124 3110 /* We assume the client took too long to RENEW. */ ··· 3194 3180 clp = list_entry(pos, struct nfs4_client, cl_lru); 3195 3181 dprintk("NFSD: purging unused client (clientid %08x)\n", 3196 3182 clp->cl_clientid.cl_id); 3197 - nfsd4_client_record_remove(clp); 3198 3183 expire_client(clp); 3199 3184 } 3200 3185 spin_lock(&recall_lock); ··· 3385 3372 return nfs_ok; 3386 3373 } 3387 3374 3388 - static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) 3375 + static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions) 3389 3376 { 3390 3377 struct nfs4_client *cl; 3391 3378 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); ··· 3394 3381 return nfserr_bad_stateid; 3395 3382 if (STALE_STATEID(stateid, nn)) 3396 3383 return nfserr_stale_stateid; 3397 - cl = find_confirmed_client(&stateid->si_opaque.so_clid); 3384 + cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions); 3398 3385 if (!cl) 3399 3386 return nfserr_expired; 3400 3387 *s = find_stateid_by_type(cl, stateid, typemask); ··· 3427 3414 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3428 3415 return check_special_stateids(net, current_fh, stateid, flags); 3429 3416 3430 - status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); 3417 + status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion); 3431 3418 if (status) 3432 3419 return status; 3433 3420 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); ··· 3577 3564 seqid, STATEID_VAL(stateid)); 3578 3565 3579 3566 *stpp = NULL; 3580 - status = nfsd4_lookup_stateid(stateid, typemask, &s); 3567 + status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion); 3581 3568 if (status) 3582 3569 return status; 3583 3570 *stpp = openlockstateid(s); ··· 3778 3765 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3779 3766 3780 3767 nfsd4_close_open_stateid(stp); 3768 + release_last_closed_stateid(oo); 3781 3769 oo->oo_last_closed_stid = stp; 3782 3770 3783 3771 if (list_empty(&oo->oo_owner.so_stateids)) { ··· 3815 3801 inode = cstate->current_fh.fh_dentry->d_inode; 3816 3802 3817 3803 nfs4_lock_state(); 3818 - status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s); 3804 + status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion); 3819 3805 if (status) 3820 3806 goto out; 3821 3807 dp = delegstateid(s); ··· 4059 4045 struct nfs4_lockowner *lock_sop = NULL; 4060 4046 struct nfs4_ol_stateid *lock_stp; 4061 4047 struct file *filp = NULL; 4062 - struct file_lock file_lock; 4063 - struct file_lock conflock; 4048 + struct file_lock *file_lock = NULL; 4049 + struct file_lock *conflock = NULL; 4064 4050 __be32 status = 0; 4065 4051 bool new_state = false; 4066 4052 int lkflg; ··· 4130 4116 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim) 4131 4117 goto out; 4132 4118 4133 - locks_init_lock(&file_lock); 4119 + file_lock = locks_alloc_lock(); 4120 + if (!file_lock) { 4121 + dprintk("NFSD: %s: unable to allocate lock!\n", __func__); 4122 + status = nfserr_jukebox; 4123 + goto out; 4124 + } 4125 + 4126 + locks_init_lock(file_lock); 4134 4127 switch (lock->lk_type) { 4135 4128 case NFS4_READ_LT: 4136 4129 case NFS4_READW_LT: 4137 4130 filp = find_readable_file(lock_stp->st_file); 4138 4131 if (filp) 4139 4132 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); 4140 - file_lock.fl_type = F_RDLCK; 4133 + file_lock->fl_type = F_RDLCK; 4141 4134 break; 4142 4135 case NFS4_WRITE_LT: 4143 4136 case NFS4_WRITEW_LT: 4144 4137 filp = find_writeable_file(lock_stp->st_file); 4145 4138 if (filp) 4146 4139 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); 4147 - file_lock.fl_type = F_WRLCK; 4140 + file_lock->fl_type = F_WRLCK; 4148 4141 break; 4149 4142 default: 4150 4143 status = nfserr_inval; ··· 4161 4140 status = nfserr_openmode; 4162 4141 goto out; 4163 4142 } 4164 - file_lock.fl_owner = (fl_owner_t)lock_sop; 4165 - file_lock.fl_pid = current->tgid; 4166 - file_lock.fl_file = filp; 4167 - file_lock.fl_flags = FL_POSIX; 4168 - file_lock.fl_lmops = &nfsd_posix_mng_ops; 4143 + file_lock->fl_owner = (fl_owner_t)lock_sop; 4144 + file_lock->fl_pid = current->tgid; 4145 + file_lock->fl_file = filp; 4146 + file_lock->fl_flags = FL_POSIX; 4147 + file_lock->fl_lmops = &nfsd_posix_mng_ops; 4148 + file_lock->fl_start = lock->lk_offset; 4149 + file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); 4150 + nfs4_transform_lock_offset(file_lock); 4169 4151 4170 - file_lock.fl_start = lock->lk_offset; 4171 - file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); 4172 - nfs4_transform_lock_offset(&file_lock); 4152 + conflock = locks_alloc_lock(); 4153 + if (!conflock) { 4154 + dprintk("NFSD: %s: unable to allocate lock!\n", __func__); 4155 + status = nfserr_jukebox; 4156 + goto out; 4157 + } 4173 4158 4174 - /* 4175 - * Try to lock the file in the VFS. 4176 - * Note: locks.c uses the BKL to protect the inode's lock list. 4177 - */ 4178 - 4179 - err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); 4159 + err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); 4180 4160 switch (-err) { 4181 4161 case 0: /* success! */ 4182 4162 update_stateid(&lock_stp->st_stid.sc_stateid); ··· 4188 4166 case (EAGAIN): /* conflock holds conflicting lock */ 4189 4167 status = nfserr_denied; 4190 4168 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); 4191 - nfs4_set_lock_denied(&conflock, &lock->lk_denied); 4169 + nfs4_set_lock_denied(conflock, &lock->lk_denied); 4192 4170 break; 4193 4171 case (EDEADLK): 4194 4172 status = nfserr_deadlock; ··· 4203 4181 release_lockowner(lock_sop); 4204 4182 if (!cstate->replay_owner) 4205 4183 nfs4_unlock_state(); 4184 + if (file_lock) 4185 + locks_free_lock(file_lock); 4186 + if (conflock) 4187 + locks_free_lock(conflock); 4206 4188 return status; 4207 4189 } 4208 4190 ··· 4235 4209 struct nfsd4_lockt *lockt) 4236 4210 { 4237 4211 struct inode *inode; 4238 - struct file_lock file_lock; 4212 + struct file_lock *file_lock = NULL; 4239 4213 struct nfs4_lockowner *lo; 4240 4214 __be32 status; 4241 4215 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); ··· 4256 4230 goto out; 4257 4231 4258 4232 inode = cstate->current_fh.fh_dentry->d_inode; 4259 - locks_init_lock(&file_lock); 4233 + file_lock = locks_alloc_lock(); 4234 + if (!file_lock) { 4235 + dprintk("NFSD: %s: unable to allocate lock!\n", __func__); 4236 + status = nfserr_jukebox; 4237 + goto out; 4238 + } 4239 + locks_init_lock(file_lock); 4260 4240 switch (lockt->lt_type) { 4261 4241 case NFS4_READ_LT: 4262 4242 case NFS4_READW_LT: 4263 - file_lock.fl_type = F_RDLCK; 4243 + file_lock->fl_type = F_RDLCK; 4264 4244 break; 4265 4245 case NFS4_WRITE_LT: 4266 4246 case NFS4_WRITEW_LT: 4267 - file_lock.fl_type = F_WRLCK; 4247 + file_lock->fl_type = F_WRLCK; 4268 4248 break; 4269 4249 default: 4270 4250 dprintk("NFSD: nfs4_lockt: bad lock type!\n"); ··· 4280 4248 4281 4249 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); 4282 4250 if (lo) 4283 - file_lock.fl_owner = (fl_owner_t)lo; 4284 - file_lock.fl_pid = current->tgid; 4285 - file_lock.fl_flags = FL_POSIX; 4251 + file_lock->fl_owner = (fl_owner_t)lo; 4252 + file_lock->fl_pid = current->tgid; 4253 + file_lock->fl_flags = FL_POSIX; 4286 4254 4287 - file_lock.fl_start = lockt->lt_offset; 4288 - file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); 4255 + file_lock->fl_start = lockt->lt_offset; 4256 + file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); 4289 4257 4290 - nfs4_transform_lock_offset(&file_lock); 4258 + nfs4_transform_lock_offset(file_lock); 4291 4259 4292 - status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); 4260 + status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock); 4293 4261 if (status) 4294 4262 goto out; 4295 4263 4296 - if (file_lock.fl_type != F_UNLCK) { 4264 + if (file_lock->fl_type != F_UNLCK) { 4297 4265 status = nfserr_denied; 4298 - nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); 4266 + nfs4_set_lock_denied(file_lock, &lockt->lt_denied); 4299 4267 } 4300 4268 out: 4301 4269 nfs4_unlock_state(); 4270 + if (file_lock) 4271 + locks_free_lock(file_lock); 4302 4272 return status; 4303 4273 } 4304 4274 ··· 4310 4276 { 4311 4277 struct nfs4_ol_stateid *stp; 4312 4278 struct file *filp = NULL; 4313 - struct file_lock file_lock; 4279 + struct file_lock *file_lock = NULL; 4314 4280 __be32 status; 4315 4281 int err; 4316 4282 ··· 4332 4298 status = nfserr_lock_range; 4333 4299 goto out; 4334 4300 } 4335 - BUG_ON(!filp); 4336 - locks_init_lock(&file_lock); 4337 - file_lock.fl_type = F_UNLCK; 4338 - file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); 4339 - file_lock.fl_pid = current->tgid; 4340 - file_lock.fl_file = filp; 4341 - file_lock.fl_flags = FL_POSIX; 4342 - file_lock.fl_lmops = &nfsd_posix_mng_ops; 4343 - file_lock.fl_start = locku->lu_offset; 4301 + file_lock = locks_alloc_lock(); 4302 + if (!file_lock) { 4303 + dprintk("NFSD: %s: unable to allocate lock!\n", __func__); 4304 + status = nfserr_jukebox; 4305 + goto out; 4306 + } 4307 + locks_init_lock(file_lock); 4308 + file_lock->fl_type = F_UNLCK; 4309 + file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); 4310 + file_lock->fl_pid = current->tgid; 4311 + file_lock->fl_file = filp; 4312 + file_lock->fl_flags = FL_POSIX; 4313 + file_lock->fl_lmops = &nfsd_posix_mng_ops; 4314 + file_lock->fl_start = locku->lu_offset; 4344 4315 4345 - file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length); 4346 - nfs4_transform_lock_offset(&file_lock); 4316 + file_lock->fl_end = last_byte_offset(locku->lu_offset, 4317 + locku->lu_length); 4318 + nfs4_transform_lock_offset(file_lock); 4347 4319 4348 4320 /* 4349 4321 * Try to unlock the file in the VFS. 4350 4322 */ 4351 - err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL); 4323 + err = vfs_lock_file(filp, F_SETLK, file_lock, NULL); 4352 4324 if (err) { 4353 4325 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); 4354 4326 goto out_nfserr; ··· 4368 4328 out: 4369 4329 if (!cstate->replay_owner) 4370 4330 nfs4_unlock_state(); 4331 + if (file_lock) 4332 + locks_free_lock(file_lock); 4371 4333 return status; 4372 4334 4373 4335 out_nfserr: ··· 4543 4501 * Called from OPEN. Look for clientid in reclaim list. 4544 4502 */ 4545 4503 __be32 4546 - nfs4_check_open_reclaim(clientid_t *clid) 4504 + nfs4_check_open_reclaim(clientid_t *clid, bool sessions) 4547 4505 { 4548 4506 struct nfs4_client *clp; 4549 4507 4550 4508 /* find clientid in conf_id_hashtbl */ 4551 - clp = find_confirmed_client(clid); 4509 + clp = find_confirmed_client(clid, sessions); 4552 4510 if (clp == NULL) 4553 4511 return nfserr_reclaim_bad; 4554 4512 ··· 4564 4522 4565 4523 nfs4_lock_state(); 4566 4524 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { 4567 - nfsd4_client_record_remove(clp); 4568 4525 expire_client(clp); 4569 4526 if (++count == num) 4570 4527 break; ··· 4623 4582 printk(KERN_INFO "NFSD: Forgot %d open owners", count); 4624 4583 } 4625 4584 4626 - int nfsd_process_n_delegations(u64 num, struct list_head *list) 4585 + static int nfsd_process_n_delegations(u64 num, struct list_head *list) 4627 4586 { 4628 4587 int i, count = 0; 4629 4588 struct nfs4_file *fp, *fnext; ··· 4788 4747 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 4789 4748 while (!list_empty(&conf_id_hashtbl[i])) { 4790 4749 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); 4791 - expire_client(clp); 4750 + destroy_client(clp); 4792 4751 } 4793 4752 while (!list_empty(&unconf_str_hashtbl[i])) { 4794 4753 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash); 4795 - expire_client(clp); 4754 + destroy_client(clp); 4796 4755 } 4797 4756 } 4798 4757 INIT_LIST_HEAD(&reaplist);
+1 -1
fs/nfsd/nfs4xdr.c
··· 2659 2659 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); 2660 2660 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); 2661 2661 WRITE32(bcts->dir); 2662 - /* XXX: ? */ 2662 + /* Sorry, we do not yet support RDMA over 4.1: */ 2663 2663 WRITE32(0); 2664 2664 ADJUST_ARGS(); 2665 2665 }
+2 -82
fs/nfsd/nfsctl.c
··· 406 406 return rv; 407 407 if (newthreads < 0) 408 408 return -EINVAL; 409 - rv = nfsd_svc(NFS_PORT, newthreads); 409 + rv = nfsd_svc(newthreads); 410 410 if (rv < 0) 411 411 return rv; 412 412 } else ··· 683 683 } 684 684 685 685 /* 686 - * A '-' followed by the 'name' of a socket means we close the socket. 687 - */ 688 - static ssize_t __write_ports_delfd(char *buf) 689 - { 690 - char *toclose; 691 - int len = 0; 692 - 693 - toclose = kstrdup(buf + 1, GFP_KERNEL); 694 - if (toclose == NULL) 695 - return -ENOMEM; 696 - 697 - if (nfsd_serv != NULL) 698 - len = svc_sock_names(nfsd_serv, buf, 699 - SIMPLE_TRANSACTION_LIMIT, toclose); 700 - kfree(toclose); 701 - return len; 702 - } 703 - 704 - /* 705 686 * A transport listener is added by writing it's transport name and 706 687 * a port number. 707 688 */ ··· 693 712 int port, err; 694 713 struct net *net = &init_net; 695 714 696 - if (sscanf(buf, "%15s %4u", transport, &port) != 2) 715 + if (sscanf(buf, "%15s %5u", transport, &port) != 2) 697 716 return -EINVAL; 698 717 699 718 if (port < 1 || port > USHRT_MAX) ··· 727 746 return err; 728 747 } 729 748 730 - /* 731 - * A transport listener is removed by writing a "-", it's transport 732 - * name, and it's port number. 733 - */ 734 - static ssize_t __write_ports_delxprt(char *buf) 735 - { 736 - struct svc_xprt *xprt; 737 - char transport[16]; 738 - int port; 739 - 740 - if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2) 741 - return -EINVAL; 742 - 743 - if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL) 744 - return -EINVAL; 745 - 746 - xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port); 747 - if (xprt == NULL) 748 - return -ENOTCONN; 749 - 750 - svc_close_xprt(xprt); 751 - svc_xprt_put(xprt); 752 - return 0; 753 - } 754 - 755 749 static ssize_t __write_ports(struct file *file, char *buf, size_t size) 756 750 { 757 751 if (size == 0) ··· 735 779 if (isdigit(buf[0])) 736 780 return __write_ports_addfd(buf); 737 781 738 - if (buf[0] == '-' && isdigit(buf[1])) 739 - return __write_ports_delfd(buf); 740 - 741 782 if (isalpha(buf[0])) 742 783 return __write_ports_addxprt(buf); 743 - 744 - if (buf[0] == '-' && isalpha(buf[1])) 745 - return __write_ports_delxprt(buf); 746 784 747 785 return -EINVAL; 748 786 } ··· 775 825 * OR 776 826 * 777 827 * Input: 778 - * buf: C string containing a "-" followed 779 - * by an integer value representing a 780 - * previously passed in socket file 781 - * descriptor 782 - * size: non-zero length of C string in @buf 783 - * Output: 784 - * On success: NFS service no longer listens on that socket; 785 - * passed-in buffer filled with a '\n'-terminated C 786 - * string containing a unique name of the listener; 787 - * return code is the size in bytes of the string 788 - * On error: return code is a negative errno value 789 - * 790 - * OR 791 - * 792 - * Input: 793 828 * buf: C string containing a transport 794 829 * name and an unsigned integer value 795 830 * representing the port to listen on, ··· 782 847 * size: non-zero length of C string in @buf 783 848 * Output: 784 849 * On success: returns zero; NFS service is started 785 - * On error: return code is a negative errno value 786 - * 787 - * OR 788 - * 789 - * Input: 790 - * buf: C string containing a "-" followed 791 - * by a transport name and an unsigned 792 - * integer value representing the port 793 - * to listen on, separated by whitespace 794 - * size: non-zero length of C string in @buf 795 - * Output: 796 - * On success: returns zero; NFS service no longer listens 797 - * on that transport 798 850 * On error: return code is a negative errno value 799 851 */ 800 852 static ssize_t write_ports(struct file *file, char *buf, size_t size) ··· 929 1007 { 930 1008 return nfsd4_write_time(file, buf, size, &nfsd4_grace); 931 1009 } 932 - 933 - extern char *nfs4_recoverydir(void); 934 1010 935 1011 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) 936 1012 {
+3 -1
fs/nfsd/nfsd.h
··· 65 65 /* 66 66 * Function prototypes. 67 67 */ 68 - int nfsd_svc(unsigned short port, int nrservs); 68 + int nfsd_svc(int nrservs); 69 69 int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); 70 70 71 71 int nfsd_nrthreads(void); ··· 124 124 void nfs4_state_shutdown(void); 125 125 void nfs4_reset_lease(time_t leasetime); 126 126 int nfs4_reset_recoverydir(char *recdir); 127 + char * nfs4_recoverydir(void); 127 128 #else 128 129 static inline void nfs4_state_init(void) { } 129 130 static inline int nfsd4_init_slabs(void) { return 0; } ··· 133 132 static inline void nfs4_state_shutdown(void) { } 134 133 static inline void nfs4_reset_lease(time_t leasetime) { } 135 134 static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } 135 + static inline char * nfs4_recoverydir(void) {return NULL; } 136 136 #endif 137 137 138 138 /*
+8 -18
fs/nfsd/nfssvc.c
··· 183 183 return rv; 184 184 } 185 185 186 - static int nfsd_init_socks(int port) 186 + static int nfsd_init_socks(void) 187 187 { 188 188 int error; 189 189 if (!list_empty(&nfsd_serv->sv_permsocks)) 190 190 return 0; 191 191 192 - error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port, 192 + error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, NFS_PORT, 193 193 SVC_SOCK_DEFAULTS); 194 194 if (error < 0) 195 195 return error; 196 196 197 - error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port, 197 + error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, NFS_PORT, 198 198 SVC_SOCK_DEFAULTS); 199 199 if (error < 0) 200 200 return error; ··· 204 204 205 205 static bool nfsd_up = false; 206 206 207 - static int nfsd_startup(unsigned short port, int nrservs) 207 + static int nfsd_startup(int nrservs) 208 208 { 209 209 int ret; 210 210 ··· 218 218 ret = nfsd_racache_init(2*nrservs); 219 219 if (ret) 220 220 return ret; 221 - ret = nfsd_init_socks(port); 221 + ret = nfsd_init_socks(); 222 222 if (ret) 223 223 goto out_racache; 224 224 ret = lockd_up(&init_net); ··· 436 436 * this is the first time nrservs is nonzero. 437 437 */ 438 438 int 439 - nfsd_svc(unsigned short port, int nrservs) 439 + nfsd_svc(int nrservs) 440 440 { 441 441 int error; 442 442 bool nfsd_up_before; ··· 458 458 459 459 nfsd_up_before = nfsd_up; 460 460 461 - error = nfsd_startup(port, nrservs); 461 + error = nfsd_startup(nrservs); 462 462 if (error) 463 463 goto out_destroy; 464 464 error = svc_set_num_threads(nfsd_serv, NULL, nrservs); ··· 487 487 nfsd(void *vrqstp) 488 488 { 489 489 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 490 - int err, preverr = 0; 490 + int err; 491 491 492 492 /* Lock module and set up kernel thread */ 493 493 mutex_lock(&nfsd_mutex); ··· 534 534 ; 535 535 if (err == -EINTR) 536 536 break; 537 - else if (err < 0) { 538 - if (err != preverr) { 539 - printk(KERN_WARNING "%s: unexpected error " 540 - "from svc_recv (%d)\n", __func__, -err); 541 - preverr = err; 542 - } 543 - schedule_timeout_uninterruptible(HZ); 544 - continue; 545 - } 546 - 547 537 validate_process_creds(); 548 538 svc_process(rqstp); 549 539 validate_process_creds();
+2 -6
fs/nfsd/state.h
··· 373 373 return container_of(so, struct nfs4_lockowner, lo_owner); 374 374 } 375 375 376 - /* 377 - * nfs4_file: a file opened by some number of (open) nfs4_stateowners. 378 - * o fi_perfile list is used to search for conflicting 379 - * share_acces, share_deny on the file. 380 - */ 376 + /* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */ 381 377 struct nfs4_file { 382 378 atomic_t fi_ref; 383 379 struct list_head fi_hash; /* hash by "struct inode *" */ ··· 455 459 extern int nfs4_in_grace(void); 456 460 extern void nfs4_release_reclaim(void); 457 461 extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); 458 - extern __be32 nfs4_check_open_reclaim(clientid_t *clid); 462 + extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); 459 463 extern void nfs4_free_openowner(struct nfs4_openowner *); 460 464 extern void nfs4_free_lockowner(struct nfs4_lockowner *); 461 465 extern int set_callback_cred(void);
+1 -1
fs/nfsd/vfs.c
··· 1581 1581 */ 1582 1582 1583 1583 oldfs = get_fs(); set_fs(KERNEL_DS); 1584 - host_err = inode->i_op->readlink(path.dentry, buf, *lenp); 1584 + host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp); 1585 1585 set_fs(oldfs); 1586 1586 1587 1587 if (host_err < 0)
-5
include/linux/nfsd/Kbuild
··· 1 - header-y += cld.h 2 - header-y += debug.h 3 - header-y += export.h 4 - header-y += nfsfh.h 5 - header-y += stats.h
include/linux/nfsd/cld.h include/uapi/linux/nfsd/cld.h
+1 -30
include/linux/nfsd/debug.h
··· 5 5 * 6 6 * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> 7 7 */ 8 - 9 8 #ifndef LINUX_NFSD_DEBUG_H 10 9 #define LINUX_NFSD_DEBUG_H 11 10 12 - #include <linux/sunrpc/debug.h> 11 + #include <uapi/linux/nfsd/debug.h> 13 12 14 - /* 15 - * Enable debugging for nfsd. 16 - * Requires RPC_DEBUG. 17 - */ 18 - #ifdef RPC_DEBUG 19 - # define NFSD_DEBUG 1 20 - #endif 21 - 22 - /* 23 - * knfsd debug flags 24 - */ 25 - #define NFSDDBG_SOCK 0x0001 26 - #define NFSDDBG_FH 0x0002 27 - #define NFSDDBG_EXPORT 0x0004 28 - #define NFSDDBG_SVC 0x0008 29 - #define NFSDDBG_PROC 0x0010 30 - #define NFSDDBG_FILEOP 0x0020 31 - #define NFSDDBG_AUTH 0x0040 32 - #define NFSDDBG_REPCACHE 0x0080 33 - #define NFSDDBG_XDR 0x0100 34 - #define NFSDDBG_LOCKD 0x0200 35 - #define NFSDDBG_ALL 0x7FFF 36 - #define NFSDDBG_NOCHANGE 0xFFFF 37 - 38 - 39 - #ifdef __KERNEL__ 40 13 # undef ifdebug 41 14 # ifdef NFSD_DEBUG 42 15 # define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag) 43 16 # else 44 17 # define ifdebug(flag) if (0) 45 18 # endif 46 - #endif /* __KERNEL__ */ 47 - 48 19 #endif /* LINUX_NFSD_DEBUG_H */
+1 -51
include/linux/nfsd/export.h
··· 6 6 * 7 7 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> 8 8 */ 9 - 10 9 #ifndef NFSD_EXPORT_H 11 10 #define NFSD_EXPORT_H 12 11 13 - # include <linux/types.h> 14 - #ifdef __KERNEL__ 15 12 # include <linux/nfsd/nfsfh.h> 16 - #endif 17 - 18 - /* 19 - * Important limits for the exports stuff. 20 - */ 21 - #define NFSCLNT_IDMAX 1024 22 - #define NFSCLNT_ADDRMAX 16 23 - #define NFSCLNT_KEYMAX 32 24 - 25 - /* 26 - * Export flags. 27 - */ 28 - #define NFSEXP_READONLY 0x0001 29 - #define NFSEXP_INSECURE_PORT 0x0002 30 - #define NFSEXP_ROOTSQUASH 0x0004 31 - #define NFSEXP_ALLSQUASH 0x0008 32 - #define NFSEXP_ASYNC 0x0010 33 - #define NFSEXP_GATHERED_WRITES 0x0020 34 - /* 40 80 100 currently unused */ 35 - #define NFSEXP_NOHIDE 0x0200 36 - #define NFSEXP_NOSUBTREECHECK 0x0400 37 - #define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */ 38 - #define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect; no longer supported */ 39 - #define NFSEXP_FSID 0x2000 40 - #define NFSEXP_CROSSMOUNT 0x4000 41 - #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ 42 - /* 43 - * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4 44 - * clients, and only to the single directory that is the root of the 45 - * export; further lookup and readdir operations are treated as if every 46 - * subdirectory was a mountpoint, and ignored if they are not themselves 47 - * exported. This is used by nfsd and mountd to construct the NFSv4 48 - * pseudofilesystem, which provides access only to paths leading to each 49 - * exported filesystem. 50 - */ 51 - #define NFSEXP_V4ROOT 0x10000 52 - /* All flags that we claim to support. (Note we don't support NOACL.) */ 53 - #define NFSEXP_ALLFLAGS 0x17E3F 54 - 55 - /* The flags that may vary depending on security flavor: */ 56 - #define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \ 57 - | NFSEXP_ALLSQUASH \ 58 - | NFSEXP_INSECURE_PORT) 59 - 60 - #ifdef __KERNEL__ 13 + #include <uapi/linux/nfsd/export.h> 61 14 62 15 /* 63 16 * FS Locations ··· 107 154 } 108 155 struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *); 109 156 110 - #endif /* __KERNEL__ */ 111 - 112 157 #endif /* NFSD_EXPORT_H */ 113 -
+1 -110
include/linux/nfsd/nfsfh.h
··· 10 10 * 11 11 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 12 12 */ 13 - 14 13 #ifndef _LINUX_NFSD_FH_H 15 14 #define _LINUX_NFSD_FH_H 16 15 17 - #include <linux/types.h> 18 - #include <linux/nfs.h> 19 - #include <linux/nfs2.h> 20 - #include <linux/nfs3.h> 21 - #include <linux/nfs4.h> 22 - #ifdef __KERNEL__ 23 16 # include <linux/sunrpc/svc.h> 24 - #endif 25 - 26 - /* 27 - * This is the old "dentry style" Linux NFSv2 file handle. 28 - * 29 - * The xino and xdev fields are currently used to transport the 30 - * ino/dev of the exported inode. 31 - */ 32 - struct nfs_fhbase_old { 33 - __u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */ 34 - __u32 fb_ino; /* our inode number */ 35 - __u32 fb_dirino; /* dir inode number, 0 for directories */ 36 - __u32 fb_dev; /* our device */ 37 - __u32 fb_xdev; 38 - __u32 fb_xino; 39 - __u32 fb_generation; 40 - }; 41 - 42 - /* 43 - * This is the new flexible, extensible style NFSv2/v3 file handle. 44 - * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000 45 - * 46 - * The file handle starts with a sequence of four-byte words. 47 - * The first word contains a version number (1) and three descriptor bytes 48 - * that tell how the remaining 3 variable length fields should be handled. 49 - * These three bytes are auth_type, fsid_type and fileid_type. 50 - * 51 - * All four-byte values are in host-byte-order. 52 - * 53 - * The auth_type field specifies how the filehandle can be authenticated 54 - * This might allow a file to be confirmed to be in a writable part of a 55 - * filetree without checking the path from it up to the root. 56 - * Current values: 57 - * 0 - No authentication. fb_auth is 0 bytes long 58 - * Possible future values: 59 - * 1 - 4 bytes taken from MD5 hash of the remainer of the file handle 60 - * prefixed by a secret and with the important export flags. 61 - * 62 - * The fsid_type identifies how the filesystem (or export point) is 63 - * encoded. 64 - * Current values: 65 - * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number 66 - * NOTE: we cannot use the kdev_t device id value, because kdev_t.h 67 - * says we mustn't. We must break it up and reassemble. 68 - * 1 - 4 byte user specified identifier 69 - * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED 70 - * 3 - 4 byte device id, encoded for user-space, 4 byte inode number 71 - * 4 - 4 byte inode number and 4 byte uuid 72 - * 5 - 8 byte uuid 73 - * 6 - 16 byte uuid 74 - * 7 - 8 byte inode number and 16 byte uuid 75 - * 76 - * The fileid_type identified how the file within the filesystem is encoded. 77 - * This is (will be) passed to, and set by, the underlying filesystem if it supports 78 - * filehandle operations. The filesystem must not use the value '0' or '0xff' and may 79 - * only use the values 1 and 2 as defined below: 80 - * Current values: 81 - * 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes. 82 - * 1 - 32bit inode number, 32 bit generation number. 83 - * 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number. 84 - * 85 - */ 86 - struct nfs_fhbase_new { 87 - __u8 fb_version; /* == 1, even => nfs_fhbase_old */ 88 - __u8 fb_auth_type; 89 - __u8 fb_fsid_type; 90 - __u8 fb_fileid_type; 91 - __u32 fb_auth[1]; 92 - /* __u32 fb_fsid[0]; floating */ 93 - /* __u32 fb_fileid[0]; floating */ 94 - }; 95 - 96 - struct knfsd_fh { 97 - unsigned int fh_size; /* significant for NFSv3. 98 - * Points to the current size while building 99 - * a new file handle 100 - */ 101 - union { 102 - struct nfs_fhbase_old fh_old; 103 - __u32 fh_pad[NFS4_FHSIZE/4]; 104 - struct nfs_fhbase_new fh_new; 105 - } fh_base; 106 - }; 107 - 108 - #define ofh_dcookie fh_base.fh_old.fb_dcookie 109 - #define ofh_ino fh_base.fh_old.fb_ino 110 - #define ofh_dirino fh_base.fh_old.fb_dirino 111 - #define ofh_dev fh_base.fh_old.fb_dev 112 - #define ofh_xdev fh_base.fh_old.fb_xdev 113 - #define ofh_xino fh_base.fh_old.fb_xino 114 - #define ofh_generation fh_base.fh_old.fb_generation 115 - 116 - #define fh_version fh_base.fh_new.fb_version 117 - #define fh_fsid_type fh_base.fh_new.fb_fsid_type 118 - #define fh_auth_type fh_base.fh_new.fb_auth_type 119 - #define fh_fileid_type fh_base.fh_new.fb_fileid_type 120 - #define fh_auth fh_base.fh_new.fb_auth 121 - #define fh_fsid fh_base.fh_new.fb_auth 122 - 123 - #ifdef __KERNEL__ 17 + #include <uapi/linux/nfsd/nfsfh.h> 124 18 125 19 static inline __u32 ino_t_to_u32(ino_t ino) 126 20 { ··· 59 165 #endif /* CONFIG_NFSD_V3 */ 60 166 61 167 } svc_fh; 62 - 63 - #endif /* __KERNEL__ */ 64 - 65 168 66 169 #endif /* _LINUX_NFSD_FH_H */
+1 -7
include/linux/nfsd/stats.h
··· 5 5 * 6 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 7 */ 8 - 9 8 #ifndef LINUX_NFSD_STATS_H 10 9 #define LINUX_NFSD_STATS_H 11 10 12 - #include <linux/nfs4.h> 11 + #include <uapi/linux/nfsd/stats.h> 13 12 14 - /* thread usage wraps very million seconds (approx one fortnight) */ 15 - #define NFSD_USAGE_WRAP (HZ*1000000) 16 - 17 - #ifdef __KERNEL__ 18 13 19 14 struct nfsd_stats { 20 15 unsigned int rchits; /* repcache hits */ ··· 42 47 void nfsd_stat_init(void); 43 48 void nfsd_stat_shutdown(void); 44 49 45 - #endif /* __KERNEL__ */ 46 50 #endif /* LINUX_NFSD_STATS_H */
-1
include/linux/sunrpc/Kbuild
··· 1 - header-y += debug.h
+1 -38
include/linux/sunrpc/debug.h
··· 5 5 * 6 6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 7 7 */ 8 - 9 8 #ifndef _LINUX_SUNRPC_DEBUG_H_ 10 9 #define _LINUX_SUNRPC_DEBUG_H_ 11 10 12 - /* 13 - * RPC debug facilities 14 - */ 15 - #define RPCDBG_XPRT 0x0001 16 - #define RPCDBG_CALL 0x0002 17 - #define RPCDBG_DEBUG 0x0004 18 - #define RPCDBG_NFS 0x0008 19 - #define RPCDBG_AUTH 0x0010 20 - #define RPCDBG_BIND 0x0020 21 - #define RPCDBG_SCHED 0x0040 22 - #define RPCDBG_TRANS 0x0080 23 - #define RPCDBG_SVCXPRT 0x0100 24 - #define RPCDBG_SVCDSP 0x0200 25 - #define RPCDBG_MISC 0x0400 26 - #define RPCDBG_CACHE 0x0800 27 - #define RPCDBG_ALL 0x7fff 11 + #include <uapi/linux/sunrpc/debug.h> 28 12 29 - #ifdef __KERNEL__ 30 13 31 14 /* 32 15 * Enable RPC debugging/profiling. ··· 69 86 void rpc_register_sysctl(void); 70 87 void rpc_unregister_sysctl(void); 71 88 #endif 72 - 73 - #endif /* __KERNEL__ */ 74 - 75 - /* 76 - * Declarations for the sysctl debug interface, which allows to read or 77 - * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc 78 - * module currently registers its sysctl table dynamically, the sysctl path 79 - * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>. 80 - */ 81 - 82 - enum { 83 - CTL_RPCDEBUG = 1, 84 - CTL_NFSDEBUG, 85 - CTL_NFSDDEBUG, 86 - CTL_NLMDEBUG, 87 - CTL_SLOTTABLE_UDP, 88 - CTL_SLOTTABLE_TCP, 89 - CTL_MIN_RESVPORT, 90 - CTL_MAX_RESVPORT, 91 - }; 92 89 93 90 #endif /* _LINUX_SUNRPC_DEBUG_H_ */
+2 -3
include/linux/sunrpc/svc_xprt.h
··· 114 114 int svc_create_xprt(struct svc_serv *, const char *, struct net *, 115 115 const int, const unsigned short, int); 116 116 void svc_xprt_enqueue(struct svc_xprt *xprt); 117 - void svc_xprt_received(struct svc_xprt *); 118 117 void svc_xprt_put(struct svc_xprt *xprt); 119 118 void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt); 120 119 void svc_close_xprt(struct svc_xprt *xprt); ··· 123 124 struct net *net, const sa_family_t af, 124 125 const unsigned short port); 125 126 int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); 127 + void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt); 126 128 127 129 static inline void svc_xprt_get(struct svc_xprt *xprt) 128 130 { ··· 166 166 case AF_INET6: 167 167 return sizeof(struct sockaddr_in6); 168 168 } 169 - 170 - return 0; 169 + BUG(); 171 170 } 172 171 173 172 static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt)
-3
include/linux/sunrpc/svcsock.h
··· 39 39 int svc_send(struct svc_rqst *); 40 40 void svc_drop(struct svc_rqst *); 41 41 void svc_sock_update_bufs(struct svc_serv *serv); 42 - int svc_sock_names(struct svc_serv *serv, char *buf, 43 - const size_t buflen, 44 - const char *toclose); 45 42 int svc_addsock(struct svc_serv *serv, const int fd, 46 43 char *name_return, const size_t len); 47 44 void svc_init_xprt_sock(void);
+5
include/uapi/linux/nfsd/Kbuild
··· 1 1 # UAPI Header export list 2 + header-y += cld.h 3 + header-y += debug.h 4 + header-y += export.h 5 + header-y += nfsfh.h 6 + header-y += stats.h
+40
include/uapi/linux/nfsd/debug.h
··· 1 + /* 2 + * linux/include/linux/nfsd/debug.h 3 + * 4 + * Debugging-related stuff for nfsd 5 + * 6 + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> 7 + */ 8 + 9 + #ifndef _UAPILINUX_NFSD_DEBUG_H 10 + #define _UAPILINUX_NFSD_DEBUG_H 11 + 12 + #include <linux/sunrpc/debug.h> 13 + 14 + /* 15 + * Enable debugging for nfsd. 16 + * Requires RPC_DEBUG. 17 + */ 18 + #ifdef RPC_DEBUG 19 + # define NFSD_DEBUG 1 20 + #endif 21 + 22 + /* 23 + * knfsd debug flags 24 + */ 25 + #define NFSDDBG_SOCK 0x0001 26 + #define NFSDDBG_FH 0x0002 27 + #define NFSDDBG_EXPORT 0x0004 28 + #define NFSDDBG_SVC 0x0008 29 + #define NFSDDBG_PROC 0x0010 30 + #define NFSDDBG_FILEOP 0x0020 31 + #define NFSDDBG_AUTH 0x0040 32 + #define NFSDDBG_REPCACHE 0x0080 33 + #define NFSDDBG_XDR 0x0100 34 + #define NFSDDBG_LOCKD 0x0200 35 + #define NFSDDBG_ALL 0x7FFF 36 + #define NFSDDBG_NOCHANGE 0xFFFF 37 + 38 + 39 + 40 + #endif /* _UAPILINUX_NFSD_DEBUG_H */
+58
include/uapi/linux/nfsd/export.h
··· 1 + /* 2 + * include/linux/nfsd/export.h 3 + * 4 + * Public declarations for NFS exports. The definitions for the 5 + * syscall interface are in nfsctl.h 6 + * 7 + * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> 8 + */ 9 + 10 + #ifndef _UAPINFSD_EXPORT_H 11 + #define _UAPINFSD_EXPORT_H 12 + 13 + # include <linux/types.h> 14 + 15 + /* 16 + * Important limits for the exports stuff. 17 + */ 18 + #define NFSCLNT_IDMAX 1024 19 + #define NFSCLNT_ADDRMAX 16 20 + #define NFSCLNT_KEYMAX 32 21 + 22 + /* 23 + * Export flags. 24 + */ 25 + #define NFSEXP_READONLY 0x0001 26 + #define NFSEXP_INSECURE_PORT 0x0002 27 + #define NFSEXP_ROOTSQUASH 0x0004 28 + #define NFSEXP_ALLSQUASH 0x0008 29 + #define NFSEXP_ASYNC 0x0010 30 + #define NFSEXP_GATHERED_WRITES 0x0020 31 + /* 40 80 100 currently unused */ 32 + #define NFSEXP_NOHIDE 0x0200 33 + #define NFSEXP_NOSUBTREECHECK 0x0400 34 + #define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */ 35 + #define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect; no longer supported */ 36 + #define NFSEXP_FSID 0x2000 37 + #define NFSEXP_CROSSMOUNT 0x4000 38 + #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ 39 + /* 40 + * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4 41 + * clients, and only to the single directory that is the root of the 42 + * export; further lookup and readdir operations are treated as if every 43 + * subdirectory was a mountpoint, and ignored if they are not themselves 44 + * exported. This is used by nfsd and mountd to construct the NFSv4 45 + * pseudofilesystem, which provides access only to paths leading to each 46 + * exported filesystem. 47 + */ 48 + #define NFSEXP_V4ROOT 0x10000 49 + /* All flags that we claim to support. (Note we don't support NOACL.) */ 50 + #define NFSEXP_ALLFLAGS 0x17E3F 51 + 52 + /* The flags that may vary depending on security flavor: */ 53 + #define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \ 54 + | NFSEXP_ALLSQUASH \ 55 + | NFSEXP_INSECURE_PORT) 56 + 57 + 58 + #endif /* _UAPINFSD_EXPORT_H */
+122
include/uapi/linux/nfsd/nfsfh.h
··· 1 + /* 2 + * include/linux/nfsd/nfsfh.h 3 + * 4 + * This file describes the layout of the file handles as passed 5 + * over the wire. 6 + * 7 + * Earlier versions of knfsd used to sign file handles using keyed MD5 8 + * or SHA. I've removed this code, because it doesn't give you more 9 + * security than blocking external access to port 2049 on your firewall. 10 + * 11 + * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 12 + */ 13 + 14 + #ifndef _UAPI_LINUX_NFSD_FH_H 15 + #define _UAPI_LINUX_NFSD_FH_H 16 + 17 + #include <linux/types.h> 18 + #include <linux/nfs.h> 19 + #include <linux/nfs2.h> 20 + #include <linux/nfs3.h> 21 + #include <linux/nfs4.h> 22 + 23 + /* 24 + * This is the old "dentry style" Linux NFSv2 file handle. 25 + * 26 + * The xino and xdev fields are currently used to transport the 27 + * ino/dev of the exported inode. 28 + */ 29 + struct nfs_fhbase_old { 30 + __u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */ 31 + __u32 fb_ino; /* our inode number */ 32 + __u32 fb_dirino; /* dir inode number, 0 for directories */ 33 + __u32 fb_dev; /* our device */ 34 + __u32 fb_xdev; 35 + __u32 fb_xino; 36 + __u32 fb_generation; 37 + }; 38 + 39 + /* 40 + * This is the new flexible, extensible style NFSv2/v3 file handle. 41 + * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000 42 + * 43 + * The file handle starts with a sequence of four-byte words. 44 + * The first word contains a version number (1) and three descriptor bytes 45 + * that tell how the remaining 3 variable length fields should be handled. 46 + * These three bytes are auth_type, fsid_type and fileid_type. 47 + * 48 + * All four-byte values are in host-byte-order. 49 + * 50 + * The auth_type field specifies how the filehandle can be authenticated 51 + * This might allow a file to be confirmed to be in a writable part of a 52 + * filetree without checking the path from it up to the root. 53 + * Current values: 54 + * 0 - No authentication. fb_auth is 0 bytes long 55 + * Possible future values: 56 + * 1 - 4 bytes taken from MD5 hash of the remainer of the file handle 57 + * prefixed by a secret and with the important export flags. 58 + * 59 + * The fsid_type identifies how the filesystem (or export point) is 60 + * encoded. 61 + * Current values: 62 + * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number 63 + * NOTE: we cannot use the kdev_t device id value, because kdev_t.h 64 + * says we mustn't. We must break it up and reassemble. 65 + * 1 - 4 byte user specified identifier 66 + * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED 67 + * 3 - 4 byte device id, encoded for user-space, 4 byte inode number 68 + * 4 - 4 byte inode number and 4 byte uuid 69 + * 5 - 8 byte uuid 70 + * 6 - 16 byte uuid 71 + * 7 - 8 byte inode number and 16 byte uuid 72 + * 73 + * The fileid_type identified how the file within the filesystem is encoded. 74 + * This is (will be) passed to, and set by, the underlying filesystem if it supports 75 + * filehandle operations. The filesystem must not use the value '0' or '0xff' and may 76 + * only use the values 1 and 2 as defined below: 77 + * Current values: 78 + * 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes. 79 + * 1 - 32bit inode number, 32 bit generation number. 80 + * 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number. 81 + * 82 + */ 83 + struct nfs_fhbase_new { 84 + __u8 fb_version; /* == 1, even => nfs_fhbase_old */ 85 + __u8 fb_auth_type; 86 + __u8 fb_fsid_type; 87 + __u8 fb_fileid_type; 88 + __u32 fb_auth[1]; 89 + /* __u32 fb_fsid[0]; floating */ 90 + /* __u32 fb_fileid[0]; floating */ 91 + }; 92 + 93 + struct knfsd_fh { 94 + unsigned int fh_size; /* significant for NFSv3. 95 + * Points to the current size while building 96 + * a new file handle 97 + */ 98 + union { 99 + struct nfs_fhbase_old fh_old; 100 + __u32 fh_pad[NFS4_FHSIZE/4]; 101 + struct nfs_fhbase_new fh_new; 102 + } fh_base; 103 + }; 104 + 105 + #define ofh_dcookie fh_base.fh_old.fb_dcookie 106 + #define ofh_ino fh_base.fh_old.fb_ino 107 + #define ofh_dirino fh_base.fh_old.fb_dirino 108 + #define ofh_dev fh_base.fh_old.fb_dev 109 + #define ofh_xdev fh_base.fh_old.fb_xdev 110 + #define ofh_xino fh_base.fh_old.fb_xino 111 + #define ofh_generation fh_base.fh_old.fb_generation 112 + 113 + #define fh_version fh_base.fh_new.fb_version 114 + #define fh_fsid_type fh_base.fh_new.fb_fsid_type 115 + #define fh_auth_type fh_base.fh_new.fb_auth_type 116 + #define fh_fileid_type fh_base.fh_new.fb_fileid_type 117 + #define fh_auth fh_base.fh_new.fb_auth 118 + #define fh_fsid fh_base.fh_new.fb_auth 119 + 120 + 121 + 122 + #endif /* _UAPI_LINUX_NFSD_FH_H */
+17
include/uapi/linux/nfsd/stats.h
··· 1 + /* 2 + * linux/include/linux/nfsd/stats.h 3 + * 4 + * Statistics for NFS server. 5 + * 6 + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 + */ 8 + 9 + #ifndef _UAPILINUX_NFSD_STATS_H 10 + #define _UAPILINUX_NFSD_STATS_H 11 + 12 + #include <linux/nfs4.h> 13 + 14 + /* thread usage wraps very million seconds (approx one fortnight) */ 15 + #define NFSD_USAGE_WRAP (HZ*1000000) 16 + 17 + #endif /* _UAPILINUX_NFSD_STATS_H */
+1
include/uapi/linux/sunrpc/Kbuild
··· 1 1 # UAPI Header export list 2 + header-y += debug.h
+48
include/uapi/linux/sunrpc/debug.h
··· 1 + /* 2 + * linux/include/linux/sunrpc/debug.h 3 + * 4 + * Debugging support for sunrpc module 5 + * 6 + * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 7 + */ 8 + 9 + #ifndef _UAPI_LINUX_SUNRPC_DEBUG_H_ 10 + #define _UAPI_LINUX_SUNRPC_DEBUG_H_ 11 + 12 + /* 13 + * RPC debug facilities 14 + */ 15 + #define RPCDBG_XPRT 0x0001 16 + #define RPCDBG_CALL 0x0002 17 + #define RPCDBG_DEBUG 0x0004 18 + #define RPCDBG_NFS 0x0008 19 + #define RPCDBG_AUTH 0x0010 20 + #define RPCDBG_BIND 0x0020 21 + #define RPCDBG_SCHED 0x0040 22 + #define RPCDBG_TRANS 0x0080 23 + #define RPCDBG_SVCXPRT 0x0100 24 + #define RPCDBG_SVCDSP 0x0200 25 + #define RPCDBG_MISC 0x0400 26 + #define RPCDBG_CACHE 0x0800 27 + #define RPCDBG_ALL 0x7fff 28 + 29 + 30 + /* 31 + * Declarations for the sysctl debug interface, which allows to read or 32 + * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc 33 + * module currently registers its sysctl table dynamically, the sysctl path 34 + * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>. 35 + */ 36 + 37 + enum { 38 + CTL_RPCDEBUG = 1, 39 + CTL_NFSDEBUG, 40 + CTL_NFSDDEBUG, 41 + CTL_NLMDEBUG, 42 + CTL_SLOTTABLE_UDP, 43 + CTL_SLOTTABLE_TCP, 44 + CTL_MIN_RESVPORT, 45 + CTL_MAX_RESVPORT, 46 + }; 47 + 48 + #endif /* _UAPI_LINUX_SUNRPC_DEBUG_H_ */
+138 -95
net/sunrpc/svc_xprt.c
··· 208 208 return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); 209 209 } 210 210 211 + /* 212 + * svc_xprt_received conditionally queues the transport for processing 213 + * by another thread. The caller must hold the XPT_BUSY bit and must 214 + * not thereafter touch transport data. 215 + * 216 + * Note: XPT_DATA only gets cleared when a read-attempt finds no (or 217 + * insufficient) data. 218 + */ 219 + static void svc_xprt_received(struct svc_xprt *xprt) 220 + { 221 + BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); 222 + /* As soon as we clear busy, the xprt could be closed and 223 + * 'put', so we need a reference to call svc_xprt_enqueue with: 224 + */ 225 + svc_xprt_get(xprt); 226 + clear_bit(XPT_BUSY, &xprt->xpt_flags); 227 + svc_xprt_enqueue(xprt); 228 + svc_xprt_put(xprt); 229 + } 230 + 231 + void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new) 232 + { 233 + clear_bit(XPT_TEMP, &new->xpt_flags); 234 + spin_lock_bh(&serv->sv_lock); 235 + list_add(&new->xpt_list, &serv->sv_permsocks); 236 + spin_unlock_bh(&serv->sv_lock); 237 + svc_xprt_received(new); 238 + } 239 + 211 240 int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, 212 241 struct net *net, const int family, 213 242 const unsigned short port, int flags) ··· 261 232 module_put(xcl->xcl_owner); 262 233 return PTR_ERR(newxprt); 263 234 } 264 - 265 - clear_bit(XPT_TEMP, &newxprt->xpt_flags); 266 - spin_lock_bh(&serv->sv_lock); 267 - list_add(&newxprt->xpt_list, &serv->sv_permsocks); 268 - spin_unlock_bh(&serv->sv_lock); 235 + svc_add_new_perm_xprt(serv, newxprt); 269 236 newport = svc_xprt_local_port(newxprt); 270 - clear_bit(XPT_BUSY, &newxprt->xpt_flags); 271 237 return newport; 272 238 } 273 239 err: ··· 418 394 return xprt; 419 395 } 420 396 421 - /* 422 - * svc_xprt_received conditionally queues the transport for processing 423 - * by another thread. The caller must hold the XPT_BUSY bit and must 424 - * not thereafter touch transport data. 425 - * 426 - * Note: XPT_DATA only gets cleared when a read-attempt finds no (or 427 - * insufficient) data. 428 - */ 429 - void svc_xprt_received(struct svc_xprt *xprt) 430 - { 431 - BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); 432 - /* As soon as we clear busy, the xprt could be closed and 433 - * 'put', so we need a reference to call svc_xprt_enqueue with: 434 - */ 435 - svc_xprt_get(xprt); 436 - clear_bit(XPT_BUSY, &xprt->xpt_flags); 437 - svc_xprt_enqueue(xprt); 438 - svc_xprt_put(xprt); 439 - } 440 - EXPORT_SYMBOL_GPL(svc_xprt_received); 441 - 442 397 /** 443 398 * svc_reserve - change the space reserved for the reply to a request. 444 399 * @rqstp: The request in question ··· 568 565 } 569 566 } 570 567 571 - /* 572 - * Receive the next request on any transport. This code is carefully 573 - * organised not to touch any cachelines in the shared svc_serv 574 - * structure, only cachelines in the local svc_pool. 575 - */ 576 - int svc_recv(struct svc_rqst *rqstp, long timeout) 568 + int svc_alloc_arg(struct svc_rqst *rqstp) 577 569 { 578 - struct svc_xprt *xprt = NULL; 579 - struct svc_serv *serv = rqstp->rq_server; 580 - struct svc_pool *pool = rqstp->rq_pool; 581 - int len, i; 582 - int pages; 583 - struct xdr_buf *arg; 584 - DECLARE_WAITQUEUE(wait, current); 585 - long time_left; 586 - 587 - dprintk("svc: server %p waiting for data (to = %ld)\n", 588 - rqstp, timeout); 589 - 590 - if (rqstp->rq_xprt) 591 - printk(KERN_ERR 592 - "svc_recv: service %p, transport not NULL!\n", 593 - rqstp); 594 - if (waitqueue_active(&rqstp->rq_wait)) 595 - printk(KERN_ERR 596 - "svc_recv: service %p, wait queue active!\n", 597 - rqstp); 570 + struct svc_serv *serv = rqstp->rq_server; 571 + struct xdr_buf *arg; 572 + int pages; 573 + int i; 598 574 599 575 /* now allocate needed pages. If we get a failure, sleep briefly */ 600 576 pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; ··· 603 621 arg->page_len = (pages-2)*PAGE_SIZE; 604 622 arg->len = (pages-1)*PAGE_SIZE; 605 623 arg->tail[0].iov_len = 0; 624 + return 0; 625 + } 606 626 607 - try_to_freeze(); 608 - cond_resched(); 609 - if (signalled() || kthread_should_stop()) 610 - return -EINTR; 627 + struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) 628 + { 629 + struct svc_xprt *xprt; 630 + struct svc_pool *pool = rqstp->rq_pool; 631 + DECLARE_WAITQUEUE(wait, current); 632 + long time_left; 611 633 612 634 /* Normally we will wait up to 5 seconds for any required 613 635 * cache information to be provided. ··· 649 663 if (kthread_should_stop()) { 650 664 set_current_state(TASK_RUNNING); 651 665 spin_unlock_bh(&pool->sp_lock); 652 - return -EINTR; 666 + return ERR_PTR(-EINTR); 653 667 } 654 668 655 669 add_wait_queue(&rqstp->rq_wait, &wait); ··· 670 684 spin_unlock_bh(&pool->sp_lock); 671 685 dprintk("svc: server %p, no data yet\n", rqstp); 672 686 if (signalled() || kthread_should_stop()) 673 - return -EINTR; 687 + return ERR_PTR(-EINTR); 674 688 else 675 - return -EAGAIN; 689 + return ERR_PTR(-EAGAIN); 676 690 } 677 691 } 678 692 spin_unlock_bh(&pool->sp_lock); 693 + return xprt; 694 + } 679 695 680 - len = 0; 696 + void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) 697 + { 698 + spin_lock_bh(&serv->sv_lock); 699 + set_bit(XPT_TEMP, &newxpt->xpt_flags); 700 + list_add(&newxpt->xpt_list, &serv->sv_tempsocks); 701 + serv->sv_tmpcnt++; 702 + if (serv->sv_temptimer.function == NULL) { 703 + /* setup timer to age temp transports */ 704 + setup_timer(&serv->sv_temptimer, svc_age_temp_xprts, 705 + (unsigned long)serv); 706 + mod_timer(&serv->sv_temptimer, 707 + jiffies + svc_conn_age_period * HZ); 708 + } 709 + spin_unlock_bh(&serv->sv_lock); 710 + svc_xprt_received(newxpt); 711 + } 712 + 713 + static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) 714 + { 715 + struct svc_serv *serv = rqstp->rq_server; 716 + int len = 0; 717 + 681 718 if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { 682 719 dprintk("svc_recv: found XPT_CLOSE\n"); 683 720 svc_delete_xprt(xprt); 684 721 /* Leave XPT_BUSY set on the dead xprt: */ 685 - goto out; 722 + return 0; 686 723 } 687 724 if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { 688 725 struct svc_xprt *newxpt; 726 + /* 727 + * We know this module_get will succeed because the 728 + * listener holds a reference too 729 + */ 730 + __module_get(xprt->xpt_class->xcl_owner); 731 + svc_check_conn_limits(xprt->xpt_server); 689 732 newxpt = xprt->xpt_ops->xpo_accept(xprt); 690 - if (newxpt) { 691 - /* 692 - * We know this module_get will succeed because the 693 - * listener holds a reference too 694 - */ 695 - __module_get(newxpt->xpt_class->xcl_owner); 696 - svc_check_conn_limits(xprt->xpt_server); 697 - spin_lock_bh(&serv->sv_lock); 698 - set_bit(XPT_TEMP, &newxpt->xpt_flags); 699 - list_add(&newxpt->xpt_list, &serv->sv_tempsocks); 700 - serv->sv_tmpcnt++; 701 - if (serv->sv_temptimer.function == NULL) { 702 - /* setup timer to age temp transports */ 703 - setup_timer(&serv->sv_temptimer, 704 - svc_age_temp_xprts, 705 - (unsigned long)serv); 706 - mod_timer(&serv->sv_temptimer, 707 - jiffies + svc_conn_age_period * HZ); 708 - } 709 - spin_unlock_bh(&serv->sv_lock); 710 - svc_xprt_received(newxpt); 711 - } 733 + if (newxpt) 734 + svc_add_new_temp_xprt(serv, newxpt); 712 735 } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { 736 + /* XPT_DATA|XPT_DEFERRED case: */ 713 737 dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", 714 - rqstp, pool->sp_id, xprt, 738 + rqstp, rqstp->rq_pool->sp_id, xprt, 715 739 atomic_read(&xprt->xpt_ref.refcount)); 716 740 rqstp->rq_deferred = svc_deferred_dequeue(xprt); 717 741 if (rqstp->rq_deferred) ··· 732 736 rqstp->rq_reserved = serv->sv_max_mesg; 733 737 atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); 734 738 } 739 + /* clear XPT_BUSY: */ 735 740 svc_xprt_received(xprt); 741 + return len; 742 + } 743 + 744 + /* 745 + * Receive the next request on any transport. This code is carefully 746 + * organised not to touch any cachelines in the shared svc_serv 747 + * structure, only cachelines in the local svc_pool. 748 + */ 749 + int svc_recv(struct svc_rqst *rqstp, long timeout) 750 + { 751 + struct svc_xprt *xprt = NULL; 752 + struct svc_serv *serv = rqstp->rq_server; 753 + int len, err; 754 + 755 + dprintk("svc: server %p waiting for data (to = %ld)\n", 756 + rqstp, timeout); 757 + 758 + if (rqstp->rq_xprt) 759 + printk(KERN_ERR 760 + "svc_recv: service %p, transport not NULL!\n", 761 + rqstp); 762 + if (waitqueue_active(&rqstp->rq_wait)) 763 + printk(KERN_ERR 764 + "svc_recv: service %p, wait queue active!\n", 765 + rqstp); 766 + 767 + err = svc_alloc_arg(rqstp); 768 + if (err) 769 + return err; 770 + 771 + try_to_freeze(); 772 + cond_resched(); 773 + if (signalled() || kthread_should_stop()) 774 + return -EINTR; 775 + 776 + xprt = svc_get_next_xprt(rqstp, timeout); 777 + if (IS_ERR(xprt)) 778 + return PTR_ERR(xprt); 779 + 780 + len = svc_handle_xprt(rqstp, xprt); 736 781 737 782 /* No data, incomplete (TCP) read, or accept() */ 738 - if (len == 0 || len == -EAGAIN) 783 + if (len <= 0) 739 784 goto out; 740 785 741 786 clear_bit(XPT_OLD, &xprt->xpt_flags); ··· 954 917 } 955 918 EXPORT_SYMBOL_GPL(svc_close_xprt); 956 919 957 - static void svc_close_list(struct list_head *xprt_list, struct net *net) 920 + static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) 958 921 { 959 922 struct svc_xprt *xprt; 960 923 924 + spin_lock(&serv->sv_lock); 961 925 list_for_each_entry(xprt, xprt_list, xpt_list) { 962 926 if (xprt->xpt_net != net) 963 927 continue; 964 928 set_bit(XPT_CLOSE, &xprt->xpt_flags); 965 929 set_bit(XPT_BUSY, &xprt->xpt_flags); 966 930 } 931 + spin_unlock(&serv->sv_lock); 967 932 } 968 933 969 934 static void svc_clear_pools(struct svc_serv *serv, struct net *net) ··· 988 949 } 989 950 } 990 951 991 - static void svc_clear_list(struct list_head *xprt_list, struct net *net) 952 + static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) 992 953 { 993 954 struct svc_xprt *xprt; 994 955 struct svc_xprt *tmp; 956 + LIST_HEAD(victims); 995 957 958 + spin_lock(&serv->sv_lock); 996 959 list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { 997 960 if (xprt->xpt_net != net) 998 961 continue; 999 - svc_delete_xprt(xprt); 962 + list_move(&xprt->xpt_list, &victims); 1000 963 } 1001 - list_for_each_entry(xprt, xprt_list, xpt_list) 1002 - BUG_ON(xprt->xpt_net == net); 964 + spin_unlock(&serv->sv_lock); 965 + 966 + list_for_each_entry_safe(xprt, tmp, &victims, xpt_list) 967 + svc_delete_xprt(xprt); 1003 968 } 1004 969 1005 970 void svc_close_net(struct svc_serv *serv, struct net *net) 1006 971 { 1007 - svc_close_list(&serv->sv_tempsocks, net); 1008 - svc_close_list(&serv->sv_permsocks, net); 972 + svc_close_list(serv, &serv->sv_tempsocks, net); 973 + svc_close_list(serv, &serv->sv_permsocks, net); 1009 974 1010 975 svc_clear_pools(serv, net); 1011 976 /* ··· 1017 974 * svc_xprt_enqueue will not add new entries without taking the 1018 975 * sp_lock and checking XPT_BUSY. 1019 976 */ 1020 - svc_clear_list(&serv->sv_tempsocks, net); 1021 - svc_clear_list(&serv->sv_permsocks, net); 977 + svc_clear_list(serv, &serv->sv_tempsocks, net); 978 + svc_clear_list(serv, &serv->sv_permsocks, net); 1022 979 } 1023 980 1024 981 /*
+52 -105
net/sunrpc/svcsock.c
··· 59 59 60 60 61 61 static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, 62 - int *errp, int flags); 62 + int flags); 63 63 static void svc_udp_data_ready(struct sock *, int); 64 64 static int svc_udp_recvfrom(struct svc_rqst *); 65 65 static int svc_udp_sendto(struct svc_rqst *); ··· 305 305 return len; 306 306 } 307 307 308 - /** 309 - * svc_sock_names - construct a list of listener names in a string 310 - * @serv: pointer to RPC service 311 - * @buf: pointer to a buffer to fill in with socket names 312 - * @buflen: size of the buffer to be filled 313 - * @toclose: pointer to '\0'-terminated C string containing the name 314 - * of a listener to be closed 315 - * 316 - * Fills in @buf with a '\n'-separated list of names of listener 317 - * sockets. If @toclose is not NULL, the socket named by @toclose 318 - * is closed, and is not included in the output list. 319 - * 320 - * Returns positive length of the socket name string, or a negative 321 - * errno value on error. 322 - */ 323 - int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, 324 - const char *toclose) 325 - { 326 - struct svc_sock *svsk, *closesk = NULL; 327 - int len = 0; 328 - 329 - if (!serv) 330 - return 0; 331 - 332 - spin_lock_bh(&serv->sv_lock); 333 - list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { 334 - int onelen = svc_one_sock_name(svsk, buf + len, buflen - len); 335 - if (onelen < 0) { 336 - len = onelen; 337 - break; 338 - } 339 - if (toclose && strcmp(toclose, buf + len) == 0) { 340 - closesk = svsk; 341 - svc_xprt_get(&closesk->sk_xprt); 342 - } else 343 - len += onelen; 344 - } 345 - spin_unlock_bh(&serv->sv_lock); 346 - 347 - if (closesk) { 348 - /* Should unregister with portmap, but you cannot 349 - * unregister just one protocol... 350 - */ 351 - svc_close_xprt(&closesk->sk_xprt); 352 - svc_xprt_put(&closesk->sk_xprt); 353 - } else if (toclose) 354 - return -ENOENT; 355 - return len; 356 - } 357 - EXPORT_SYMBOL_GPL(svc_sock_names); 358 - 359 308 /* 360 309 * Check input queue length 361 310 */ ··· 547 598 dprintk("svc: recvfrom returned error %d\n", -err); 548 599 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); 549 600 } 550 - return -EAGAIN; 601 + return 0; 551 602 } 552 603 len = svc_addr_len(svc_addr(rqstp)); 553 - if (len == 0) 554 - return -EAFNOSUPPORT; 555 604 rqstp->rq_addrlen = len; 556 605 if (skb->tstamp.tv64 == 0) { 557 606 skb->tstamp = ktime_get_real(); ··· 567 620 if (!svc_udp_get_dest_address(rqstp, cmh)) { 568 621 net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", 569 622 cmh->cmsg_level, cmh->cmsg_type); 570 - out_free: 571 - trace_kfree_skb(skb, svc_udp_recvfrom); 572 - skb_free_datagram_locked(svsk->sk_sk, skb); 573 - return 0; 623 + goto out_free; 574 624 } 575 625 rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); 576 626 ··· 606 662 serv->sv_stats->netudpcnt++; 607 663 608 664 return len; 665 + out_free: 666 + trace_kfree_skb(skb, svc_udp_recvfrom); 667 + skb_free_datagram_locked(svsk->sk_sk, skb); 668 + return 0; 609 669 } 610 670 611 671 static int ··· 848 900 */ 849 901 newsock->sk->sk_sndtimeo = HZ*30; 850 902 851 - if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 852 - (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) 903 + newsvsk = svc_setup_socket(serv, newsock, 904 + (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)); 905 + if (IS_ERR(newsvsk)) 853 906 goto failed; 854 907 svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); 855 908 err = kernel_getsockname(newsock, sin, &slen); ··· 1123 1174 if (len != -EAGAIN) 1124 1175 goto err_other; 1125 1176 dprintk("RPC: TCP recvfrom got EAGAIN\n"); 1126 - return -EAGAIN; 1177 + return 0; 1127 1178 err_other: 1128 1179 printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", 1129 1180 svsk->sk_xprt.xpt_server->sv_name, -len); 1130 1181 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); 1131 1182 err_noclose: 1132 - return -EAGAIN; /* record not complete */ 1183 + return 0; /* record not complete */ 1133 1184 } 1134 1185 1135 1186 /* ··· 1332 1383 */ 1333 1384 static struct svc_sock *svc_setup_socket(struct svc_serv *serv, 1334 1385 struct socket *sock, 1335 - int *errp, int flags) 1386 + int flags) 1336 1387 { 1337 1388 struct svc_sock *svsk; 1338 1389 struct sock *inet; 1339 1390 int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); 1391 + int err = 0; 1340 1392 1341 1393 dprintk("svc: svc_setup_socket %p\n", sock); 1342 - if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { 1343 - *errp = -ENOMEM; 1344 - return NULL; 1345 - } 1394 + svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); 1395 + if (!svsk) 1396 + return ERR_PTR(-ENOMEM); 1346 1397 1347 1398 inet = sock->sk; 1348 1399 1349 1400 /* Register socket with portmapper */ 1350 - if (*errp >= 0 && pmap_register) 1351 - *errp = svc_register(serv, sock_net(sock->sk), inet->sk_family, 1401 + if (pmap_register) 1402 + err = svc_register(serv, sock_net(sock->sk), inet->sk_family, 1352 1403 inet->sk_protocol, 1353 1404 ntohs(inet_sk(inet)->inet_sport)); 1354 1405 1355 - if (*errp < 0) { 1406 + if (err < 0) { 1356 1407 kfree(svsk); 1357 - return NULL; 1408 + return ERR_PTR(err); 1358 1409 } 1359 1410 1360 1411 inet->sk_user_data = svsk; ··· 1399 1450 int err = 0; 1400 1451 struct socket *so = sockfd_lookup(fd, &err); 1401 1452 struct svc_sock *svsk = NULL; 1453 + struct sockaddr_storage addr; 1454 + struct sockaddr *sin = (struct sockaddr *)&addr; 1455 + int salen; 1402 1456 1403 1457 if (!so) 1404 1458 return err; 1459 + err = -EAFNOSUPPORT; 1405 1460 if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) 1406 - err = -EAFNOSUPPORT; 1407 - else if (so->sk->sk_protocol != IPPROTO_TCP && 1461 + goto out; 1462 + err = -EPROTONOSUPPORT; 1463 + if (so->sk->sk_protocol != IPPROTO_TCP && 1408 1464 so->sk->sk_protocol != IPPROTO_UDP) 1409 - err = -EPROTONOSUPPORT; 1410 - else if (so->state > SS_UNCONNECTED) 1411 - err = -EISCONN; 1412 - else { 1413 - if (!try_module_get(THIS_MODULE)) 1414 - err = -ENOENT; 1415 - else 1416 - svsk = svc_setup_socket(serv, so, &err, 1417 - SVC_SOCK_DEFAULTS); 1418 - if (svsk) { 1419 - struct sockaddr_storage addr; 1420 - struct sockaddr *sin = (struct sockaddr *)&addr; 1421 - int salen; 1422 - if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) 1423 - svc_xprt_set_local(&svsk->sk_xprt, sin, salen); 1424 - clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); 1425 - spin_lock_bh(&serv->sv_lock); 1426 - list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks); 1427 - spin_unlock_bh(&serv->sv_lock); 1428 - svc_xprt_received(&svsk->sk_xprt); 1429 - err = 0; 1430 - } else 1431 - module_put(THIS_MODULE); 1465 + goto out; 1466 + err = -EISCONN; 1467 + if (so->state > SS_UNCONNECTED) 1468 + goto out; 1469 + err = -ENOENT; 1470 + if (!try_module_get(THIS_MODULE)) 1471 + goto out; 1472 + svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS); 1473 + if (IS_ERR(svsk)) { 1474 + module_put(THIS_MODULE); 1475 + err = PTR_ERR(svsk); 1476 + goto out; 1432 1477 } 1433 - if (err) { 1434 - sockfd_put(so); 1435 - return err; 1436 - } 1478 + if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) 1479 + svc_xprt_set_local(&svsk->sk_xprt, sin, salen); 1480 + svc_add_new_perm_xprt(serv, &svsk->sk_xprt); 1437 1481 return svc_one_sock_name(svsk, name_return, len); 1482 + out: 1483 + sockfd_put(so); 1484 + return err; 1438 1485 } 1439 1486 EXPORT_SYMBOL_GPL(svc_addsock); 1440 1487 ··· 1508 1563 goto bummer; 1509 1564 } 1510 1565 1511 - if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { 1512 - svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); 1513 - return (struct svc_xprt *)svsk; 1566 + svsk = svc_setup_socket(serv, sock, flags); 1567 + if (IS_ERR(svsk)) { 1568 + error = PTR_ERR(svsk); 1569 + goto bummer; 1514 1570 } 1515 - 1571 + svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); 1572 + return (struct svc_xprt *)svsk; 1516 1573 bummer: 1517 1574 dprintk("svc: svc_create_socket error = %d\n", -error); 1518 1575 sock_release(sock);
-4
net/sunrpc/xprtrdma/svc_rdma_transport.c
··· 578 578 list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q); 579 579 spin_unlock_bh(&listen_xprt->sc_lock); 580 580 581 - /* 582 - * Can't use svc_xprt_received here because we are not on a 583 - * rqstp thread 584 - */ 585 581 set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags); 586 582 svc_xprt_enqueue(&listen_xprt->sc_xprt); 587 583 }