aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-06-02 18:08:11 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-06-02 18:09:27 -0400
commitde52cf922a4a17d0a4cd34d697db62a01c1bd092 (patch)
tree1c12675d523eaa34e01499ae2a70dc6983a1918b
parent5b86d4ff5dce3271dff54119e06174dc22422903 (diff)
parent4776cab43fd3111618112737a257dc3ef368eddd (diff)
Merge tag 'afs-fixes-20180514' into afs-proc
backmerge AFS fixes that went into mainline and deal with the conflict in fs/afs/fsclient.c Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/afs/addr_list.c25
-rw-r--r--fs/afs/callback.c84
-rw-r--r--fs/afs/cmservice.c67
-rw-r--r--fs/afs/dir.c54
-rw-r--r--fs/afs/file.c2
-rw-r--r--fs/afs/flock.c6
-rw-r--r--fs/afs/fsclient.c28
-rw-r--r--fs/afs/inode.c19
-rw-r--r--fs/afs/internal.h25
-rw-r--r--fs/afs/rotate.c20
-rw-r--r--fs/afs/rxrpc.c18
-rw-r--r--fs/afs/security.c7
-rw-r--r--fs/afs/server.c21
-rw-r--r--fs/afs/server_list.c7
-rw-r--r--fs/afs/super.c4
-rw-r--r--fs/afs/write.c2
-rw-r--r--include/trace/events/afs.h42
17 files changed, 264 insertions, 167 deletions
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c
index 3bedfed608a2..7587fb665ff1 100644
--- a/fs/afs/addr_list.c
+++ b/fs/afs/addr_list.c
@@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
121 p = text; 121 p = text;
122 do { 122 do {
123 struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs]; 123 struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs];
124 char tdelim = delim; 124 const char *q, *stop;
125 125
126 if (*p == delim) { 126 if (*p == delim) {
127 p++; 127 p++;
@@ -130,28 +130,33 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
130 130
131 if (*p == '[') { 131 if (*p == '[') {
132 p++; 132 p++;
133 tdelim = ']'; 133 q = memchr(p, ']', end - p);
134 } else {
135 for (q = p; q < end; q++)
136 if (*q == '+' || *q == delim)
137 break;
134 } 138 }
135 139
136 if (in4_pton(p, end - p, 140 if (in4_pton(p, q - p,
137 (u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3], 141 (u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3],
138 tdelim, &p)) { 142 -1, &stop)) {
139 srx->transport.sin6.sin6_addr.s6_addr32[0] = 0; 143 srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
140 srx->transport.sin6.sin6_addr.s6_addr32[1] = 0; 144 srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
141 srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); 145 srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
142 } else if (in6_pton(p, end - p, 146 } else if (in6_pton(p, q - p,
143 srx->transport.sin6.sin6_addr.s6_addr, 147 srx->transport.sin6.sin6_addr.s6_addr,
144 tdelim, &p)) { 148 -1, &stop)) {
145 /* Nothing to do */ 149 /* Nothing to do */
146 } else { 150 } else {
147 goto bad_address; 151 goto bad_address;
148 } 152 }
149 153
150 if (tdelim == ']') { 154 if (stop != q)
151 if (p == end || *p != ']') 155 goto bad_address;
152 goto bad_address; 156
157 p = q;
158 if (q < end && *q == ']')
153 p++; 159 p++;
154 }
155 160
156 if (p < end) { 161 if (p < end) {
157 if (*p == '+') { 162 if (*p == '+') {
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index abd9a84f4e88..571437dcb252 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -23,36 +23,55 @@
23/* 23/*
24 * Set up an interest-in-callbacks record for a volume on a server and 24 * Set up an interest-in-callbacks record for a volume on a server and
25 * register it with the server. 25 * register it with the server.
26 * - Called with volume->server_sem held. 26 * - Called with vnode->io_lock held.
27 */ 27 */
28int afs_register_server_cb_interest(struct afs_vnode *vnode, 28int afs_register_server_cb_interest(struct afs_vnode *vnode,
29 struct afs_server_entry *entry) 29 struct afs_server_list *slist,
30 unsigned int index)
30{ 31{
31 struct afs_cb_interest *cbi = entry->cb_interest, *vcbi, *new, *x; 32 struct afs_server_entry *entry = &slist->servers[index];
33 struct afs_cb_interest *cbi, *vcbi, *new, *old;
32 struct afs_server *server = entry->server; 34 struct afs_server *server = entry->server;
33 35
34again: 36again:
37 if (vnode->cb_interest &&
38 likely(vnode->cb_interest == entry->cb_interest))
39 return 0;
40
41 read_lock(&slist->lock);
42 cbi = afs_get_cb_interest(entry->cb_interest);
43 read_unlock(&slist->lock);
44
35 vcbi = vnode->cb_interest; 45 vcbi = vnode->cb_interest;
36 if (vcbi) { 46 if (vcbi) {
37 if (vcbi == cbi) 47 if (vcbi == cbi) {
48 afs_put_cb_interest(afs_v2net(vnode), cbi);
38 return 0; 49 return 0;
50 }
39 51
52 /* Use a new interest in the server list for the same server
53 * rather than an old one that's still attached to a vnode.
54 */
40 if (cbi && vcbi->server == cbi->server) { 55 if (cbi && vcbi->server == cbi->server) {
41 write_seqlock(&vnode->cb_lock); 56 write_seqlock(&vnode->cb_lock);
42 vnode->cb_interest = afs_get_cb_interest(cbi); 57 old = vnode->cb_interest;
58 vnode->cb_interest = cbi;
43 write_sequnlock(&vnode->cb_lock); 59 write_sequnlock(&vnode->cb_lock);
44 afs_put_cb_interest(afs_v2net(vnode), cbi); 60 afs_put_cb_interest(afs_v2net(vnode), old);
45 return 0; 61 return 0;
46 } 62 }
47 63
64 /* Re-use the one attached to the vnode. */
48 if (!cbi && vcbi->server == server) { 65 if (!cbi && vcbi->server == server) {
49 afs_get_cb_interest(vcbi); 66 write_lock(&slist->lock);
50 x = cmpxchg(&entry->cb_interest, cbi, vcbi); 67 if (entry->cb_interest) {
51 if (x != cbi) { 68 write_unlock(&slist->lock);
52 cbi = x; 69 afs_put_cb_interest(afs_v2net(vnode), cbi);
53 afs_put_cb_interest(afs_v2net(vnode), vcbi);
54 goto again; 70 goto again;
55 } 71 }
72
73 entry->cb_interest = cbi;
74 write_unlock(&slist->lock);
56 return 0; 75 return 0;
57 } 76 }
58 } 77 }
@@ -72,13 +91,16 @@ again:
72 list_add_tail(&new->cb_link, &server->cb_interests); 91 list_add_tail(&new->cb_link, &server->cb_interests);
73 write_unlock(&server->cb_break_lock); 92 write_unlock(&server->cb_break_lock);
74 93
75 x = cmpxchg(&entry->cb_interest, cbi, new); 94 write_lock(&slist->lock);
76 if (x == cbi) { 95 if (!entry->cb_interest) {
96 entry->cb_interest = afs_get_cb_interest(new);
77 cbi = new; 97 cbi = new;
98 new = NULL;
78 } else { 99 } else {
79 cbi = x; 100 cbi = afs_get_cb_interest(entry->cb_interest);
80 afs_put_cb_interest(afs_v2net(vnode), new);
81 } 101 }
102 write_unlock(&slist->lock);
103 afs_put_cb_interest(afs_v2net(vnode), new);
82 } 104 }
83 105
84 ASSERT(cbi); 106 ASSERT(cbi);
@@ -88,11 +110,14 @@ again:
88 */ 110 */
89 write_seqlock(&vnode->cb_lock); 111 write_seqlock(&vnode->cb_lock);
90 112
91 vnode->cb_interest = afs_get_cb_interest(cbi); 113 old = vnode->cb_interest;
114 vnode->cb_interest = cbi;
92 vnode->cb_s_break = cbi->server->cb_s_break; 115 vnode->cb_s_break = cbi->server->cb_s_break;
116 vnode->cb_v_break = vnode->volume->cb_v_break;
93 clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); 117 clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
94 118
95 write_sequnlock(&vnode->cb_lock); 119 write_sequnlock(&vnode->cb_lock);
120 afs_put_cb_interest(afs_v2net(vnode), old);
96 return 0; 121 return 0;
97} 122}
98 123
@@ -171,13 +196,24 @@ static void afs_break_one_callback(struct afs_server *server,
171 if (cbi->vid != fid->vid)