aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4filelayoutdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4filelayoutdev.c')
-rw-r--r--fs/nfs/nfs4filelayoutdev.c90
1 files changed, 34 insertions, 56 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index 8ae91908f5aa..a866bbd2890a 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -45,7 +45,7 @@
45 * - incremented when a device id maps a data server already in the cache. 45 * - incremented when a device id maps a data server already in the cache.
46 * - decremented when deviceid is removed from the cache. 46 * - decremented when deviceid is removed from the cache.
47 */ 47 */
48DEFINE_SPINLOCK(nfs4_ds_cache_lock); 48static DEFINE_SPINLOCK(nfs4_ds_cache_lock);
49static LIST_HEAD(nfs4_data_server_cache); 49static LIST_HEAD(nfs4_data_server_cache);
50 50
51/* Debug routines */ 51/* Debug routines */
@@ -108,58 +108,40 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2)
108 return false; 108 return false;
109} 109}
110 110
111/* 111static bool
112 * Lookup DS by addresses. The first matching address returns true. 112_same_data_server_addrs_locked(const struct list_head *dsaddrs1,
113 * nfs4_ds_cache_lock is held 113 const struct list_head *dsaddrs2)
114 */
115static struct nfs4_pnfs_ds *
116_data_server_lookup_locked(struct list_head *dsaddrs)
117{ 114{
118 struct nfs4_pnfs_ds *ds;
119 struct nfs4_pnfs_ds_addr *da1, *da2; 115 struct nfs4_pnfs_ds_addr *da1, *da2;
120 116
121 list_for_each_entry(da1, dsaddrs, da_node) { 117 /* step through both lists, comparing as we go */
122 list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) { 118 for (da1 = list_first_entry(dsaddrs1, typeof(*da1), da_node),
123 list_for_each_entry(da2, &ds->ds_addrs, da_node) { 119 da2 = list_first_entry(dsaddrs2, typeof(*da2), da_node);
124 if (same_sockaddr( 120 da1 != NULL && da2 != NULL;
125 (struct sockaddr *)&da1->da_addr, 121 da1 = list_entry(da1->da_node.next, typeof(*da1), da_node),
126 (struct sockaddr *)&da2->da_addr)) 122 da2 = list_entry(da2->da_node.next, typeof(*da2), da_node)) {
127 return ds; 123 if (!same_sockaddr((struct sockaddr *)&da1->da_addr,
128 } 124 (struct sockaddr *)&da2->da_addr))
129 } 125 return false;
130 } 126 }
131 return NULL; 127 if (da1 == NULL && da2 == NULL)
128 return true;
129
130 return false;
132} 131}
133 132
134/* 133/*
135 * Compare two lists of addresses. 134 * Lookup DS by addresses. nfs4_ds_cache_lock is held
136 */ 135 */
137static bool 136static struct nfs4_pnfs_ds *
138_data_server_match_all_addrs_locked(struct list_head *dsaddrs1, 137_data_server_lookup_locked(const struct list_head *dsaddrs)
139 struct list_head *dsaddrs2)
140{ 138{
141 struct nfs4_pnfs_ds_addr *da1, *da2; 139 struct nfs4_pnfs_ds *ds;
142 size_t count1 = 0,
143 count2 = 0;
144
145 list_for_each_entry(da1, dsaddrs1, da_node)
146 count1++;
147
148 list_for_each_entry(da2, dsaddrs2, da_node) {
149 bool found = false;
150 count2++;
151 list_for_each_entry(da1, dsaddrs1, da_node) {
152 if (same_sockaddr((struct sockaddr *)&da1->da_addr,
153 (struct sockaddr *)&da2->da_addr)) {
154 found = true;
155 break;
156 }
157 }
158 if (!found)
159 return false;
160 }
161 140
162 return (count1 == count2); 141 list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
142 if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
143 return ds;
144 return NULL;
163} 145}
164 146
165/* 147/*
@@ -356,11 +338,6 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
356 dprintk("%s add new data server %s\n", __func__, 338 dprintk("%s add new data server %s\n", __func__,
357 ds->ds_remotestr); 339 ds->ds_remotestr);
358 } else { 340 } else {
359 if (!_data_server_match_all_addrs_locked(&tmp_ds->ds_addrs,
360 dsaddrs)) {
361 dprintk("%s: multipath address mismatch: %s != %s",
362 __func__, tmp_ds->ds_remotestr, remotestr);
363 }
364 kfree(remotestr); 341 kfree(remotestr);
365 kfree(ds); 342 kfree(ds);
366 atomic_inc(&tmp_ds->ds_count); 343 atomic_inc(&tmp_ds->ds_count);
@@ -378,7 +355,7 @@ out:
378 * Currently only supports ipv4, ipv6 and one multi-path address. 355 * Currently only supports ipv4, ipv6 and one multi-path address.
379 */ 356 */
380static struct nfs4_pnfs_ds_addr * 357static struct nfs4_pnfs_ds_addr *
381decode_ds_addr(struct xdr_stream *streamp, gfp_t gfp_flags) 358decode_ds_addr(struct net *net, struct xdr_stream *streamp, gfp_t gfp_flags)
382{ 359{
383 struct nfs4_pnfs_ds_addr *da = NULL; 360 struct nfs4_pnfs_ds_addr *da = NULL;
384 char *buf, *portstr; 361 char *buf, *portstr;
@@ -457,7 +434,7 @@ decode_ds_addr(struct xdr_stream *streamp, gfp_t gfp_flags)
457 434
458 INIT_LIST_HEAD(&da->da_node); 435 INIT_LIST_HEAD(&da->da_node);
459 436
460 if (!rpc_pton(buf, portstr-buf, (struct sockaddr *)&da->da_addr, 437 if (!rpc_pton(net, buf, portstr-buf, (struct sockaddr *)&da->da_addr,
461 sizeof(da->da_addr))) { 438 sizeof(da->da_addr))) {
462 dprintk("%s: error parsing address %s\n", __func__, buf); 439 dprintk("%s: error parsing address %s\n", __func__, buf);
463 goto out_free_da; 440 goto out_free_da;
@@ -554,7 +531,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
554 cnt = be32_to_cpup(p); 531 cnt = be32_to_cpup(p);
555 dprintk("%s stripe count %d\n", __func__, cnt); 532 dprintk("%s stripe count %d\n", __func__, cnt);
556 if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) { 533 if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) {
557 printk(KERN_WARNING "%s: stripe count %d greater than " 534 printk(KERN_WARNING "NFS: %s: stripe count %d greater than "
558 "supported maximum %d\n", __func__, 535 "supported maximum %d\n", __func__,
559 cnt, NFS4_PNFS_MAX_STRIPE_CNT); 536 cnt, NFS4_PNFS_MAX_STRIPE_CNT);
560 goto out_err_free_scratch; 537 goto out_err_free_scratch;
@@ -585,7 +562,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
585 num = be32_to_cpup(p); 562 num = be32_to_cpup(p);
586 dprintk("%s ds_num %u\n", __func__, num); 563 dprintk("%s ds_num %u\n", __func__, num);
587 if (num > NFS4_PNFS_MAX_MULTI_CNT) { 564 if (num > NFS4_PNFS_MAX_MULTI_CNT) {
588 printk(KERN_WARNING "%s: multipath count %d greater than " 565 printk(KERN_WARNING "NFS: %s: multipath count %d greater than "
589 "supported maximum %d\n", __func__, 566 "supported maximum %d\n", __func__,
590 num, NFS4_PNFS_MAX_MULTI_CNT); 567 num, NFS4_PNFS_MAX_MULTI_CNT);
591 goto out_err_free_stripe_indices; 568 goto out_err_free_stripe_indices;
@@ -593,7 +570,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
593 570
594 /* validate stripe indices are all < num */ 571 /* validate stripe indices are all < num */
595 if (max_stripe_index >= num) { 572 if (max_stripe_index >= num) {
596 printk(KERN_WARNING "%s: stripe index %u >= num ds %u\n", 573 printk(KERN_WARNING "NFS: %s: stripe index %u >= num ds %u\n",
597 __func__, max_stripe_index, num); 574 __func__, max_stripe_index, num);
598 goto out_err_free_stripe_indices; 575 goto out_err_free_stripe_indices;
599 } 576 }
@@ -625,7 +602,8 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
625 602
626 mp_count = be32_to_cpup(p); /* multipath count */ 603 mp_count = be32_to_cpup(p); /* multipath count */
627 for (j = 0; j < mp_count; j++) { 604 for (j = 0; j < mp_count; j++) {
628 da = decode_ds_addr(&stream, gfp_flags); 605 da = decode_ds_addr(NFS_SERVER(ino)->nfs_client->net,
606 &stream, gfp_flags);
629 if (da) 607 if (da)
630 list_add_tail(&da->da_node, &dsaddrs); 608 list_add_tail(&da->da_node, &dsaddrs);
631 } 609 }
@@ -686,7 +664,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl
686 664
687 new = decode_device(inode, dev, gfp_flags); 665 new = decode_device(inode, dev, gfp_flags);
688 if (!new) { 666 if (!new) {
689 printk(KERN_WARNING "%s: Could not decode or add device\n", 667 printk(KERN_WARNING "NFS: %s: Could not decode or add device\n",
690 __func__); 668 __func__);
691 return NULL; 669 return NULL;
692 } 670 }
@@ -835,7 +813,7 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
835 struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; 813 struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
836 814
837 if (ds == NULL) { 815 if (ds == NULL) {
838 printk(KERN_ERR "%s: No data server for offset index %d\n", 816 printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
839 __func__, ds_idx); 817 __func__, ds_idx);
840 return NULL; 818 return NULL;
841 } 819 }