.. | .. |
---|
22 | 22 | #include "nfsfh.h" |
---|
23 | 23 | #include "netns.h" |
---|
24 | 24 | #include "pnfs.h" |
---|
| 25 | +#include "filecache.h" |
---|
| 26 | +#include "trace.h" |
---|
25 | 27 | |
---|
26 | 28 | #define NFSDDBG_FACILITY NFSDDBG_EXPORT |
---|
27 | 29 | |
---|
.. | .. |
---|
46 | 48 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) |
---|
47 | 49 | path_put(&key->ek_path); |
---|
48 | 50 | auth_domain_put(key->ek_client); |
---|
49 | | - kfree(key); |
---|
| 51 | + kfree_rcu(key, ek_rcu); |
---|
| 52 | +} |
---|
| 53 | + |
---|
| 54 | +static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) |
---|
| 55 | +{ |
---|
| 56 | + return sunrpc_cache_pipe_upcall(cd, h); |
---|
50 | 57 | } |
---|
51 | 58 | |
---|
52 | 59 | static void expkey_request(struct cache_detail *cd, |
---|
.. | .. |
---|
139 | 146 | if (len == 0) { |
---|
140 | 147 | set_bit(CACHE_NEGATIVE, &key.h.flags); |
---|
141 | 148 | ek = svc_expkey_update(cd, &key, ek); |
---|
142 | | - if (!ek) |
---|
| 149 | + if (ek) |
---|
| 150 | + trace_nfsd_expkey_update(ek, NULL); |
---|
| 151 | + else |
---|
143 | 152 | err = -ENOMEM; |
---|
144 | 153 | } else { |
---|
145 | 154 | err = kern_path(buf, 0, &key.ek_path); |
---|
.. | .. |
---|
149 | 158 | dprintk("Found the path %s\n", buf); |
---|
150 | 159 | |
---|
151 | 160 | ek = svc_expkey_update(cd, &key, ek); |
---|
152 | | - if (!ek) |
---|
| 161 | + if (ek) |
---|
| 162 | + trace_nfsd_expkey_update(ek, buf); |
---|
| 163 | + else |
---|
153 | 164 | err = -ENOMEM; |
---|
154 | 165 | path_put(&key.ek_path); |
---|
155 | 166 | } |
---|
.. | .. |
---|
232 | 243 | return NULL; |
---|
233 | 244 | } |
---|
234 | 245 | |
---|
| 246 | +static void expkey_flush(void) |
---|
| 247 | +{ |
---|
| 248 | + /* |
---|
| 249 | + * Take the nfsd_mutex here to ensure that the file cache is not |
---|
| 250 | + * destroyed while we're in the middle of flushing. |
---|
| 251 | + */ |
---|
| 252 | + mutex_lock(&nfsd_mutex); |
---|
| 253 | + nfsd_file_cache_purge(current->nsproxy->net_ns); |
---|
| 254 | + mutex_unlock(&nfsd_mutex); |
---|
| 255 | +} |
---|
| 256 | + |
---|
235 | 257 | static const struct cache_detail svc_expkey_cache_template = { |
---|
236 | 258 | .owner = THIS_MODULE, |
---|
237 | 259 | .hash_size = EXPKEY_HASHMAX, |
---|
238 | 260 | .name = "nfsd.fh", |
---|
239 | 261 | .cache_put = expkey_put, |
---|
| 262 | + .cache_upcall = expkey_upcall, |
---|
240 | 263 | .cache_request = expkey_request, |
---|
241 | 264 | .cache_parse = expkey_parse, |
---|
242 | 265 | .cache_show = expkey_show, |
---|
.. | .. |
---|
244 | 267 | .init = expkey_init, |
---|
245 | 268 | .update = expkey_update, |
---|
246 | 269 | .alloc = expkey_alloc, |
---|
| 270 | + .flush = expkey_flush, |
---|
247 | 271 | }; |
---|
248 | 272 | |
---|
249 | 273 | static int |
---|
.. | .. |
---|
265 | 289 | struct cache_head *ch; |
---|
266 | 290 | int hash = svc_expkey_hash(item); |
---|
267 | 291 | |
---|
268 | | - ch = sunrpc_cache_lookup(cd, &item->h, hash); |
---|
| 292 | + ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash); |
---|
269 | 293 | if (ch) |
---|
270 | 294 | return container_of(ch, struct svc_expkey, h); |
---|
271 | 295 | else |
---|
.. | .. |
---|
314 | 338 | auth_domain_put(exp->ex_client); |
---|
315 | 339 | nfsd4_fslocs_free(&exp->ex_fslocs); |
---|
316 | 340 | kfree(exp->ex_uuid); |
---|
317 | | - kfree(exp); |
---|
| 341 | + kfree_rcu(exp, ex_rcu); |
---|
| 342 | +} |
---|
| 343 | + |
---|
| 344 | +static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) |
---|
| 345 | +{ |
---|
| 346 | + return sunrpc_cache_pipe_upcall(cd, h); |
---|
318 | 347 | } |
---|
319 | 348 | |
---|
320 | 349 | static void svc_export_request(struct cache_detail *cd, |
---|
.. | .. |
---|
570 | 599 | err = get_int(&mesg, &an_int); |
---|
571 | 600 | if (err) |
---|
572 | 601 | goto out3; |
---|
573 | | - exp.ex_anon_uid= make_kuid(&init_user_ns, an_int); |
---|
| 602 | + exp.ex_anon_uid= make_kuid(current_user_ns(), an_int); |
---|
574 | 603 | |
---|
575 | 604 | /* anon gid */ |
---|
576 | 605 | err = get_int(&mesg, &an_int); |
---|
577 | 606 | if (err) |
---|
578 | 607 | goto out3; |
---|
579 | | - exp.ex_anon_gid= make_kgid(&init_user_ns, an_int); |
---|
| 608 | + exp.ex_anon_gid= make_kgid(current_user_ns(), an_int); |
---|
580 | 609 | |
---|
581 | 610 | /* fsid */ |
---|
582 | 611 | err = get_int(&mesg, &an_int); |
---|
.. | .. |
---|
630 | 659 | } |
---|
631 | 660 | |
---|
632 | 661 | expp = svc_export_lookup(&exp); |
---|
633 | | - if (expp) |
---|
634 | | - expp = svc_export_update(&exp, expp); |
---|
635 | | - else |
---|
| 662 | + if (!expp) { |
---|
636 | 663 | err = -ENOMEM; |
---|
637 | | - cache_flush(); |
---|
638 | | - if (expp == NULL) |
---|
639 | | - err = -ENOMEM; |
---|
640 | | - else |
---|
| 664 | + goto out4; |
---|
| 665 | + } |
---|
| 666 | + expp = svc_export_update(&exp, expp); |
---|
| 667 | + if (expp) { |
---|
| 668 | + trace_nfsd_export_update(expp); |
---|
| 669 | + cache_flush(); |
---|
641 | 670 | exp_put(expp); |
---|
| 671 | + } else |
---|
| 672 | + err = -ENOMEM; |
---|
642 | 673 | out4: |
---|
643 | 674 | nfsd4_fslocs_free(&exp.ex_fslocs); |
---|
644 | 675 | kfree(exp.ex_uuid); |
---|
.. | .. |
---|
754 | 785 | .hash_size = EXPORT_HASHMAX, |
---|
755 | 786 | .name = "nfsd.export", |
---|
756 | 787 | .cache_put = svc_export_put, |
---|
| 788 | + .cache_upcall = svc_export_upcall, |
---|
757 | 789 | .cache_request = svc_export_request, |
---|
758 | 790 | .cache_parse = svc_export_parse, |
---|
759 | 791 | .cache_show = svc_export_show, |
---|
.. | .. |
---|
780 | 812 | struct cache_head *ch; |
---|
781 | 813 | int hash = svc_export_hash(exp); |
---|
782 | 814 | |
---|
783 | | - ch = sunrpc_cache_lookup(exp->cd, &exp->h, hash); |
---|
| 815 | + ch = sunrpc_cache_lookup_rcu(exp->cd, &exp->h, hash); |
---|
784 | 816 | if (ch) |
---|
785 | 817 | return container_of(ch, struct svc_export, h); |
---|
786 | 818 | else |
---|
.. | .. |
---|
819 | 851 | if (ek == NULL) |
---|
820 | 852 | return ERR_PTR(-ENOMEM); |
---|
821 | 853 | err = cache_check(cd, &ek->h, reqp); |
---|
822 | | - if (err) |
---|
| 854 | + if (err) { |
---|
| 855 | + trace_nfsd_exp_find_key(&key, err); |
---|
823 | 856 | return ERR_PTR(err); |
---|
| 857 | + } |
---|
824 | 858 | return ek; |
---|
825 | 859 | } |
---|
826 | 860 | |
---|
.. | .. |
---|
842 | 876 | if (exp == NULL) |
---|
843 | 877 | return ERR_PTR(-ENOMEM); |
---|
844 | 878 | err = cache_check(cd, &exp->h, reqp); |
---|
845 | | - if (err) |
---|
| 879 | + if (err) { |
---|
| 880 | + trace_nfsd_exp_get_by_name(&key, err); |
---|
846 | 881 | return ERR_PTR(err); |
---|
| 882 | + } |
---|
847 | 883 | return exp; |
---|
848 | 884 | } |
---|
849 | 885 | |
---|
.. | .. |
---|
966 | 1002 | if (nfsd4_spo_must_allow(rqstp)) |
---|
967 | 1003 | return 0; |
---|
968 | 1004 | |
---|
969 | | - return nfserr_wrongsec; |
---|
| 1005 | + return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec; |
---|
970 | 1006 | } |
---|
971 | 1007 | |
---|
972 | 1008 | /* |
---|
.. | .. |
---|
1170 | 1206 | static void exp_flags(struct seq_file *m, int flag, int fsid, |
---|
1171 | 1207 | kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc) |
---|
1172 | 1208 | { |
---|
| 1209 | + struct user_namespace *userns = m->file->f_cred->user_ns; |
---|
| 1210 | + |
---|
1173 | 1211 | show_expflags(m, flag, NFSEXP_ALLFLAGS); |
---|
1174 | 1212 | if (flag & NFSEXP_FSID) |
---|
1175 | 1213 | seq_printf(m, ",fsid=%d", fsid); |
---|
1176 | | - if (!uid_eq(anonu, make_kuid(&init_user_ns, (uid_t)-2)) && |
---|
1177 | | - !uid_eq(anonu, make_kuid(&init_user_ns, 0x10000-2))) |
---|
1178 | | - seq_printf(m, ",anonuid=%u", from_kuid(&init_user_ns, anonu)); |
---|
1179 | | - if (!gid_eq(anong, make_kgid(&init_user_ns, (gid_t)-2)) && |
---|
1180 | | - !gid_eq(anong, make_kgid(&init_user_ns, 0x10000-2))) |
---|
1181 | | - seq_printf(m, ",anongid=%u", from_kgid(&init_user_ns, anong)); |
---|
| 1214 | + if (!uid_eq(anonu, make_kuid(userns, (uid_t)-2)) && |
---|
| 1215 | + !uid_eq(anonu, make_kuid(userns, 0x10000-2))) |
---|
| 1216 | + seq_printf(m, ",anonuid=%u", from_kuid_munged(userns, anonu)); |
---|
| 1217 | + if (!gid_eq(anong, make_kgid(userns, (gid_t)-2)) && |
---|
| 1218 | + !gid_eq(anong, make_kgid(userns, 0x10000-2))) |
---|
| 1219 | + seq_printf(m, ",anongid=%u", from_kgid_munged(userns, anong)); |
---|
1182 | 1220 | if (fsloc && fsloc->locations_count > 0) { |
---|
1183 | 1221 | char *loctype = (fsloc->migrated) ? "refer" : "replicas"; |
---|
1184 | 1222 | int i; |
---|
.. | .. |
---|
1216 | 1254 | } |
---|
1217 | 1255 | |
---|
1218 | 1256 | const struct seq_operations nfs_exports_op = { |
---|
1219 | | - .start = cache_seq_start, |
---|
1220 | | - .next = cache_seq_next, |
---|
1221 | | - .stop = cache_seq_stop, |
---|
| 1257 | + .start = cache_seq_start_rcu, |
---|
| 1258 | + .next = cache_seq_next_rcu, |
---|
| 1259 | + .stop = cache_seq_stop_rcu, |
---|
1222 | 1260 | .show = e_show, |
---|
1223 | 1261 | }; |
---|
1224 | 1262 | |
---|