aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4state.c116
1 files changed, 49 insertions, 67 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f1262f73f08b..036d5f16fd7f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -776,17 +776,15 @@ free_session_slots(struct nfsd4_session *ses)
776 * We don't actually need to cache the rpc and session headers, so we 776 * We don't actually need to cache the rpc and session headers, so we
777 * can allocate a little less for each slot: 777 * can allocate a little less for each slot:
778 */ 778 */
779static inline int slot_bytes(struct nfsd4_channel_attrs *ca) 779static inline u32 slot_bytes(struct nfsd4_channel_attrs *ca)
780{ 780{
781 return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ; 781 u32 size;
782}
783
784static int nfsd4_sanitize_slot_size(u32 size)
785{
786 size -= NFSD_MIN_HDR_SEQ_SZ; /* We don't cache the rpc header */
787 size = min_t(u32, size, NFSD_SLOT_CACHE_SIZE);
788 782
789 return size; 783 if (ca->maxresp_cached < NFSD_MIN_HDR_SEQ_SZ)
784 size = 0;
785 else
786 size = ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
787 return size + sizeof(struct nfsd4_slot);
790} 788}
791 789
792/* 790/*
@@ -794,12 +792,12 @@ static int nfsd4_sanitize_slot_size(u32 size)
794 * re-negotiate active sessions and reduce their slot usage to make 792 * re-negotiate active sessions and reduce their slot usage to make
795 * room for new connections. For now we just fail the create session. 793 * room for new connections. For now we just fail the create session.
796 */ 794 */
797static int nfsd4_get_drc_mem(int slotsize, u32 num) 795static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
798{ 796{
797 u32 slotsize = slot_bytes(ca);
798 u32 num = ca->maxreqs;
799 int avail; 799 int avail;
800 800
801 num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION);
802
803 spin_lock(&nfsd_drc_lock); 801 spin_lock(&nfsd_drc_lock);
804 avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, 802 avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION,
805 nfsd_drc_max_mem - nfsd_drc_mem_used); 803 nfsd_drc_max_mem - nfsd_drc_mem_used);
@@ -810,15 +808,19 @@ static int nfsd4_get_drc_mem(int slotsize, u32 num)
810 return num; 808 return num;
811} 809}
812 810
813static void nfsd4_put_drc_mem(int slotsize, int num) 811static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca)
814{ 812{
813 int slotsize = slot_bytes(ca);
814
815 spin_lock(&nfsd_drc_lock); 815 spin_lock(&nfsd_drc_lock);
816 nfsd_drc_mem_used -= slotsize * num; 816 nfsd_drc_mem_used -= slotsize * ca->maxreqs;
817 spin_unlock(&nfsd_drc_lock); 817 spin_unlock(&nfsd_drc_lock);
818} 818}
819 819
820static struct nfsd4_session *__alloc_session(int slotsize, int numslots) 820static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs)
821{ 821{
822 int numslots = attrs->maxreqs;
823 int slotsize = slot_bytes(attrs);
822 struct nfsd4_session *new; 824 struct nfsd4_session *new;
823 int mem, i; 825 int mem, i;
824 826
@@ -831,8 +833,7 @@ static struct nfsd4_session *__alloc_session(int slotsize, int numslots)
831 return NULL; 833 return NULL;
832 /* allocate each struct nfsd4_slot and data cache in one piece */ 834 /* allocate each struct nfsd4_slot and data cache in one piece */
833 for (i = 0; i < numslots; i++) { 835 for (i = 0; i < numslots; i++) {
834 mem = sizeof(struct nfsd4_slot) + slotsize; 836 new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL);
835 new->se_slots[i] = kzalloc(mem, GFP_KERNEL);
836 if (!new->se_slots[i]) 837 if (!new->se_slots[i])
837 goto out_free; 838 goto out_free;
838 } 839 }
@@ -844,21 +845,6 @@ out_free:
844 return NULL; 845 return NULL;
845} 846}
846 847
847static void init_forechannel_attrs(struct nfsd4_channel_attrs *new,
848 struct nfsd4_channel_attrs *req,
849 int numslots, int slotsize,
850 struct nfsd_net *nn)
851{
852 u32 maxrpc = nn->nfsd_serv->sv_max_mesg;
853
854 new->maxreqs = numslots;
855 new->maxresp_cached = min_t(u32, req->maxresp_cached,
856 slotsize + NFSD_MIN_HDR_SEQ_SZ);
857 new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc);
858 new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc);
859 new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
860}
861
862static void free_conn(struct nfsd4_conn *c) 848static void free_conn(struct nfsd4_conn *c)
863{ 849{
864 svc_xprt_put(c->cn_xprt); 850 svc_xprt_put(c->cn_xprt);
@@ -960,7 +946,6 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
960 946
961static void __free_session(struct nfsd4_session *ses) 947static void __free_session(struct nfsd4_session *ses)
962{ 948{
963 nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs);
964 free_session_slots(ses); 949 free_session_slots(ses);
965 kfree(ses); 950 kfree(ses);
966} 951}
@@ -971,35 +956,10 @@ static void free_session(struct nfsd4_session *ses)
971 956
972 lockdep_assert_held(&nn->client_lock); 957 lockdep_assert_held(&nn->client_lock);
973 nfsd4_del_conns(ses); 958 nfsd4_del_conns(ses);
959 nfsd4_put_drc_mem(&ses->se_fchannel);
974 __free_session(ses); 960 __free_session(ses);
975} 961}
976 962
977static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan,
978 struct nfsd_net *nn)
979{
980 struct nfsd4_session *new;
981 int numslots, slotsize;
982 /*
983 * Note decreasing slot size below client's request may
984 * make it difficult for client to function correctly, whereas
985 * decreasing the number of slots will (just?) affect
986 * performance. When short on memory we therefore prefer to
987 * decrease number of slots instead of their size.
988 */
989 slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached);
990 numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs);
991 if (numslots < 1)
992 return NULL;
993
994 new = __alloc_session(slotsize, numslots);
995 if (!new) {
996 nfsd4_put_drc_mem(slotsize, numslots);
997 return NULL;
998 }
999 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize, nn);
1000 return new;
1001}
1002
1003static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses) 963static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
1004{ 964{
1005 int idx; 965 int idx;
@@ -1022,7 +982,8 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
1022 list_add(&new->se_perclnt, &clp->cl_sessions); 982 list_add(&new->se_perclnt, &clp->cl_sessions);
1023 spin_unlock(&clp->cl_lock); 983 spin_unlock(&clp->cl_lock);
1024 spin_unlock(&nn->client_lock); 984 spin_unlock(&nn->client_lock);
1025 985 memcpy(&new->se_fchannel, &cses->fore_channel,
986 sizeof(struct nfsd4_channel_attrs));
1026 if (cses->flags & SESSION4_BACK_CHAN) { 987 if (cses->flags & SESSION4_BACK_CHAN) {
1027 struct sockaddr *sa = svc_addr(rqstp); 988 struct sockaddr *sa = svc_addr(rqstp);
1028 /* 989 /*
@@ -1803,12 +1764,33 @@ nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses,
1803 /* seqid, slotID, slotID, slotID, status */ \ 1764 /* seqid, slotID, slotID, slotID, status */ \
1804 5 ) * sizeof(__be32)) 1765 5 ) * sizeof(__be32))
1805 1766
1806static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca) 1767static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn)
1807{ 1768{
1769 u32 maxrpc = nn->nfsd_serv->sv_max_mesg;
1770
1808 if (ca->maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ) 1771 if (ca->maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ)
1809 return nfserr_toosmall; 1772 return nfserr_toosmall;
1810 if (ca->maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ) 1773 if (ca->maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ)
1811 return nfserr_toosmall; 1774 return nfserr_toosmall;
1775 ca->headerpadsz = 0;
1776 ca->maxreq_sz = min_t(u32, ca->maxreq_sz, maxrpc);
1777 ca->maxresp_sz = min_t(u32, ca->maxresp_sz, maxrpc);
1778 ca->maxops = min_t(u32, ca->maxops, NFSD_MAX_OPS_PER_COMPOUND);
1779 ca->maxresp_cached = min_t(u32, ca->maxresp_cached,
1780 NFSD_SLOT_CACHE_SIZE + NFSD_MIN_HDR_SEQ_SZ);
1781 ca->maxreqs = min_t(u32, ca->maxreqs, NFSD_MAX_SLOTS_PER_SESSION);
1782 /