| .. | .. |
|---|
| 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 | |
|---|