export.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491
  1. #define MSNFS /* HACK HACK */
  2. /*
  3. * linux/fs/nfsd/export.c
  4. *
  5. * NFS exporting and validation.
  6. *
  7. * We maintain a list of clients, each of which has a list of
  8. * exports. To export an fs to a given client, you first have
  9. * to create the client entry with NFSCTL_ADDCLIENT, which
  10. * creates a client control block and adds it to the hash
  11. * table. Then, you call NFSCTL_EXPORT for each fs.
  12. *
  13. *
  14. * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
  15. */
  16. #include <linux/unistd.h>
  17. #include <linux/slab.h>
  18. #include <linux/stat.h>
  19. #include <linux/in.h>
  20. #include <linux/seq_file.h>
  21. #include <linux/syscalls.h>
  22. #include <linux/rwsem.h>
  23. #include <linux/dcache.h>
  24. #include <linux/namei.h>
  25. #include <linux/mount.h>
  26. #include <linux/hash.h>
  27. #include <linux/module.h>
  28. #include <linux/exportfs.h>
  29. #include <linux/sunrpc/svc.h>
  30. #include <linux/nfsd/nfsd.h>
  31. #include <linux/nfsd/nfsfh.h>
  32. #include <linux/nfsd/syscall.h>
  33. #include <linux/lockd/bind.h>
  34. #define NFSDDBG_FACILITY NFSDDBG_EXPORT
  35. typedef struct auth_domain svc_client;
  36. typedef struct svc_export svc_export;
  37. static void exp_do_unexport(svc_export *unexp);
  38. static int exp_verify_string(char *cp, int max);
  39. /*
  40. * We have two caches.
  41. * One maps client+vfsmnt+dentry to export options - the export map
  42. * The other maps client+filehandle-fragment to export options. - the expkey map
  43. *
  44. * The export options are actually stored in the first map, and the
  45. * second map contains a reference to the entry in the first map.
  46. */
  47. #define EXPKEY_HASHBITS 8
  48. #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
  49. #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
  50. static struct cache_head *expkey_table[EXPKEY_HASHMAX];
  51. static void expkey_put(struct kref *ref)
  52. {
  53. struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
  54. if (test_bit(CACHE_VALID, &key->h.flags) &&
  55. !test_bit(CACHE_NEGATIVE, &key->h.flags)) {
  56. dput(key->ek_dentry);
  57. mntput(key->ek_mnt);
  58. }
  59. auth_domain_put(key->ek_client);
  60. kfree(key);
  61. }
  62. static void expkey_request(struct cache_detail *cd,
  63. struct cache_head *h,
  64. char **bpp, int *blen)
  65. {
  66. /* client fsidtype \xfsid */
  67. struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
  68. char type[5];
  69. qword_add(bpp, blen, ek->ek_client->name);
  70. snprintf(type, 5, "%d", ek->ek_fsidtype);
  71. qword_add(bpp, blen, type);
  72. qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
  73. (*bpp)[-1] = '\n';
  74. }
  75. static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
  76. static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
  77. static struct cache_detail svc_expkey_cache;
  78. static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
  79. {
  80. /* client fsidtype fsid [path] */
  81. char *buf;
  82. int len;
  83. struct auth_domain *dom = NULL;
  84. int err;
  85. int fsidtype;
  86. char *ep;
  87. struct svc_expkey key;
  88. struct svc_expkey *ek;
  89. if (mesg[mlen-1] != '\n')
  90. return -EINVAL;
  91. mesg[mlen-1] = 0;
  92. buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  93. err = -ENOMEM;
  94. if (!buf) goto out;
  95. err = -EINVAL;
  96. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  97. goto out;
  98. err = -ENOENT;
  99. dom = auth_domain_find(buf);
  100. if (!dom)
  101. goto out;
  102. dprintk("found domain %s\n", buf);
  103. err = -EINVAL;
  104. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  105. goto out;
  106. fsidtype = simple_strtoul(buf, &ep, 10);
  107. if (*ep)
  108. goto out;
  109. dprintk("found fsidtype %d\n", fsidtype);
  110. if (key_len(fsidtype)==0) /* invalid type */
  111. goto out;
  112. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  113. goto out;
  114. dprintk("found fsid length %d\n", len);
  115. if (len != key_len(fsidtype))
  116. goto out;
  117. /* OK, we seem to have a valid key */
  118. key.h.flags = 0;
  119. key.h.expiry_time = get_expiry(&mesg);
  120. if (key.h.expiry_time == 0)
  121. goto out;
  122. key.ek_client = dom;
  123. key.ek_fsidtype = fsidtype;
  124. memcpy(key.ek_fsid, buf, len);
  125. ek = svc_expkey_lookup(&key);
  126. err = -ENOMEM;
  127. if (!ek)
  128. goto out;
  129. /* now we want a pathname, or empty meaning NEGATIVE */
  130. err = -EINVAL;
  131. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
  132. goto out;
  133. dprintk("Path seems to be <%s>\n", buf);
  134. err = 0;
  135. if (len == 0) {
  136. set_bit(CACHE_NEGATIVE, &key.h.flags);
  137. ek = svc_expkey_update(&key, ek);
  138. if (ek)
  139. cache_put(&ek->h, &svc_expkey_cache);
  140. else err = -ENOMEM;
  141. } else {
  142. struct nameidata nd;
  143. err = path_lookup(buf, 0, &nd);
  144. if (err)
  145. goto out;
  146. dprintk("Found the path %s\n", buf);
  147. key.ek_mnt = nd.mnt;
  148. key.ek_dentry = nd.dentry;
  149. ek = svc_expkey_update(&key, ek);
  150. if (ek)
  151. cache_put(&ek->h, &svc_expkey_cache);
  152. else
  153. err = -ENOMEM;
  154. path_release(&nd);
  155. }
  156. cache_flush();
  157. out:
  158. if (dom)
  159. auth_domain_put(dom);
  160. kfree(buf);
  161. return err;
  162. }
  163. static int expkey_show(struct seq_file *m,
  164. struct cache_detail *cd,
  165. struct cache_head *h)
  166. {
  167. struct svc_expkey *ek ;
  168. int i;
  169. if (h ==NULL) {
  170. seq_puts(m, "#domain fsidtype fsid [path]\n");
  171. return 0;
  172. }
  173. ek = container_of(h, struct svc_expkey, h);
  174. seq_printf(m, "%s %d 0x", ek->ek_client->name,
  175. ek->ek_fsidtype);
  176. for (i=0; i < key_len(ek->ek_fsidtype)/4; i++)
  177. seq_printf(m, "%08x", ek->ek_fsid[i]);
  178. if (test_bit(CACHE_VALID, &h->flags) &&
  179. !test_bit(CACHE_NEGATIVE, &h->flags)) {
  180. seq_printf(m, " ");
  181. seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n");
  182. }
  183. seq_printf(m, "\n");
  184. return 0;
  185. }
  186. static inline int expkey_match (struct cache_head *a, struct cache_head *b)
  187. {
  188. struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
  189. struct svc_expkey *new = container_of(b, struct svc_expkey, h);
  190. if (orig->ek_fsidtype != new->ek_fsidtype ||
  191. orig->ek_client != new->ek_client ||
  192. memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
  193. return 0;
  194. return 1;
  195. }
  196. static inline void expkey_init(struct cache_head *cnew,
  197. struct cache_head *citem)
  198. {
  199. struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
  200. struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
  201. kref_get(&item->ek_client->ref);
  202. new->ek_client = item->ek_client;
  203. new->ek_fsidtype = item->ek_fsidtype;
  204. memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid));
  205. }
  206. static inline void expkey_update(struct cache_head *cnew,
  207. struct cache_head *citem)
  208. {
  209. struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
  210. struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
  211. new->ek_mnt = mntget(item->ek_mnt);
  212. new->ek_dentry = dget(item->ek_dentry);
  213. }
  214. static struct cache_head *expkey_alloc(void)
  215. {
  216. struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
  217. if (i)
  218. return &i->h;
  219. else
  220. return NULL;
  221. }
  222. static struct cache_detail svc_expkey_cache = {
  223. .owner = THIS_MODULE,
  224. .hash_size = EXPKEY_HASHMAX,
  225. .hash_table = expkey_table,
  226. .name = "nfsd.fh",
  227. .cache_put = expkey_put,
  228. .cache_request = expkey_request,
  229. .cache_parse = expkey_parse,
  230. .cache_show = expkey_show,
  231. .match = expkey_match,
  232. .init = expkey_init,
  233. .update = expkey_update,
  234. .alloc = expkey_alloc,
  235. };
  236. static struct svc_expkey *
  237. svc_expkey_lookup(struct svc_expkey *item)
  238. {
  239. struct cache_head *ch;
  240. int hash = item->ek_fsidtype;
  241. char * cp = (char*)item->ek_fsid;
  242. int len = key_len(item->ek_fsidtype);
  243. hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
  244. hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
  245. hash &= EXPKEY_HASHMASK;
  246. ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h,
  247. hash);
  248. if (ch)
  249. return container_of(ch, struct svc_expkey, h);
  250. else
  251. return NULL;
  252. }
  253. static struct svc_expkey *
  254. svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
  255. {
  256. struct cache_head *ch;
  257. int hash = new->ek_fsidtype;
  258. char * cp = (char*)new->ek_fsid;
  259. int len = key_len(new->ek_fsidtype);
  260. hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
  261. hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS);
  262. hash &= EXPKEY_HASHMASK;
  263. ch = sunrpc_cache_update(&svc_expkey_cache, &new->h,
  264. &old->h, hash);
  265. if (ch)
  266. return container_of(ch, struct svc_expkey, h);
  267. else
  268. return NULL;
  269. }
  270. #define EXPORT_HASHBITS 8
  271. #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
  272. #define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
  273. static struct cache_head *export_table[EXPORT_HASHMAX];
  274. static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc)
  275. {
  276. int i;
  277. for (i = 0; i < fsloc->locations_count; i++) {
  278. kfree(fsloc->locations[i].path);
  279. kfree(fsloc->locations[i].hosts);
  280. }
  281. kfree(fsloc->locations);
  282. }
  283. static void svc_export_put(struct kref *ref)
  284. {
  285. struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
  286. dput(exp->ex_dentry);
  287. mntput(exp->ex_mnt);
  288. auth_domain_put(exp->ex_client);
  289. kfree(exp->ex_path);
  290. nfsd4_fslocs_free(&exp->ex_fslocs);
  291. kfree(exp);
  292. }
  293. static void svc_export_request(struct cache_detail *cd,
  294. struct cache_head *h,
  295. char **bpp, int *blen)
  296. {
  297. /* client path */
  298. struct svc_export *exp = container_of(h, struct svc_export, h);
  299. char *pth;
  300. qword_add(bpp, blen, exp->ex_client->name);
  301. pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen);
  302. if (IS_ERR(pth)) {
  303. /* is this correct? */
  304. (*bpp)[0] = '\n';
  305. return;
  306. }
  307. qword_add(bpp, blen, pth);
  308. (*bpp)[-1] = '\n';
  309. }
  310. static struct svc_export *svc_export_update(struct svc_export *new,
  311. struct svc_export *old);
  312. static struct svc_export *svc_export_lookup(struct svc_export *);
  313. static int check_export(struct inode *inode, int flags, unsigned char *uuid)
  314. {
  315. /* We currently export only dirs and regular files.
  316. * This is what umountd does.
  317. */
  318. if (!S_ISDIR(inode->i_mode) &&
  319. !S_ISREG(inode->i_mode))
  320. return -ENOTDIR;
  321. /* There are two requirements on a filesystem to be exportable.
  322. * 1: We must be able to identify the filesystem from a number.
  323. * either a device number (so FS_REQUIRES_DEV needed)
  324. * or an FSID number (so NFSEXP_FSID or ->uuid is needed).
  325. * 2: We must be able to find an inode from a filehandle.
  326. * This means that s_export_op must be set.
  327. */
  328. if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
  329. !(flags & NFSEXP_FSID) &&
  330. uuid == NULL) {
  331. dprintk("exp_export: export of non-dev fs without fsid\n");
  332. return -EINVAL;
  333. }
  334. if (!inode->i_sb->s_export_op) {
  335. dprintk("exp_export: export of invalid fs type.\n");
  336. return -EINVAL;
  337. }
  338. /* Ok, we can export it */;
  339. if (!inode->i_sb->s_export_op->find_exported_dentry)
  340. inode->i_sb->s_export_op->find_exported_dentry =
  341. find_exported_dentry;
  342. return 0;
  343. }
  344. #ifdef CONFIG_NFSD_V4
  345. static int
  346. fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
  347. {
  348. int len;
  349. int migrated, i, err;
  350. /* listsize */
  351. err = get_int(mesg, &fsloc->locations_count);
  352. if (err)
  353. return err;
  354. if (fsloc->locations_count > MAX_FS_LOCATIONS)
  355. return -EINVAL;
  356. if (fsloc->locations_count == 0)
  357. return 0;
  358. fsloc->locations = kzalloc(fsloc->locations_count
  359. * sizeof(struct nfsd4_fs_location), GFP_KERNEL);
  360. if (!fsloc->locations)
  361. return -ENOMEM;
  362. for (i=0; i < fsloc->locations_count; i++) {
  363. /* colon separated host list */
  364. err = -EINVAL;
  365. len = qword_get(mesg, buf, PAGE_SIZE);
  366. if (len <= 0)
  367. goto out_free_all;
  368. err = -ENOMEM;
  369. fsloc->locations[i].hosts = kstrdup(buf, GFP_KERNEL);
  370. if (!fsloc->locations[i].hosts)
  371. goto out_free_all;
  372. err = -EINVAL;
  373. /* slash separated path component list */
  374. len = qword_get(mesg, buf, PAGE_SIZE);
  375. if (len <= 0)
  376. goto out_free_all;
  377. err = -ENOMEM;
  378. fsloc->locations[i].path = kstrdup(buf, GFP_KERNEL);
  379. if (!fsloc->locations[i].path)
  380. goto out_free_all;
  381. }
  382. /* migrated */
  383. err = get_int(mesg, &migrated);
  384. if (err)
  385. goto out_free_all;
  386. err = -EINVAL;
  387. if (migrated < 0 || migrated > 1)
  388. goto out_free_all;
  389. fsloc->migrated = migrated;
  390. return 0;
  391. out_free_all:
  392. nfsd4_fslocs_free(fsloc);
  393. return err;
  394. }
  395. #else /* CONFIG_NFSD_V4 */
  396. static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
  397. #endif
  398. static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
  399. {
  400. /* client path expiry [flags anonuid anongid fsid] */
  401. char *buf;
  402. int len;
  403. int err;
  404. struct auth_domain *dom = NULL;
  405. struct nameidata nd;
  406. struct svc_export exp, *expp;
  407. int an_int;
  408. nd.dentry = NULL;
  409. exp.ex_path = NULL;
  410. /* fs locations */
  411. exp.ex_fslocs.locations = NULL;
  412. exp.ex_fslocs.locations_count = 0;
  413. exp.ex_fslocs.migrated = 0;
  414. exp.ex_uuid = NULL;
  415. if (mesg[mlen-1] != '\n')
  416. return -EINVAL;
  417. mesg[mlen-1] = 0;
  418. buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  419. err = -ENOMEM;
  420. if (!buf) goto out;
  421. /* client */
  422. len = qword_get(&mesg, buf, PAGE_SIZE);
  423. err = -EINVAL;
  424. if (len <= 0) goto out;
  425. err = -ENOENT;
  426. dom = auth_domain_find(buf);
  427. if (!dom)
  428. goto out;
  429. /* path */
  430. err = -EINVAL;
  431. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  432. goto out;
  433. err = path_lookup(buf, 0, &nd);
  434. if (err) goto out_no_path;
  435. exp.h.flags = 0;
  436. exp.ex_client = dom;
  437. exp.ex_mnt = nd.mnt;
  438. exp.ex_dentry = nd.dentry;
  439. exp.ex_path = kstrdup(buf, GFP_KERNEL);
  440. err = -ENOMEM;
  441. if (!exp.ex_path)
  442. goto out;
  443. /* expiry */
  444. err = -EINVAL;
  445. exp.h.expiry_time = get_expiry(&mesg);
  446. if (exp.h.expiry_time == 0)
  447. goto out;
  448. /* flags */
  449. err = get_int(&mesg, &an_int);
  450. if (err == -ENOENT)
  451. set_bit(CACHE_NEGATIVE, &exp.h.flags);
  452. else {
  453. if (err || an_int < 0) goto out;
  454. exp.ex_flags= an_int;
  455. /* anon uid */
  456. err = get_int(&mesg, &an_int);
  457. if (err) goto out;
  458. exp.ex_anon_uid= an_int;
  459. /* anon gid */
  460. err = get_int(&mesg, &an_int);
  461. if (err) goto out;
  462. exp.ex_anon_gid= an_int;
  463. /* fsid */
  464. err = get_int(&mesg, &an_int);
  465. if (err) goto out;
  466. exp.ex_fsid = an_int;
  467. while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
  468. if (strcmp(buf, "fsloc") == 0)
  469. err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
  470. else if (strcmp(buf, "uuid") == 0) {
  471. /* expect a 16 byte uuid encoded as \xXXXX... */
  472. len = qword_get(&mesg, buf, PAGE_SIZE);
  473. if (len != 16)
  474. err = -EINVAL;
  475. else {
  476. exp.ex_uuid =
  477. kmemdup(buf, 16, GFP_KERNEL);
  478. if (exp.ex_uuid == NULL)
  479. err = -ENOMEM;
  480. }
  481. } else
  482. /* quietly ignore unknown words and anything
  483. * following. Newer user-space can try to set
  484. * new values, then see what the result was.
  485. */
  486. break;
  487. if (err)
  488. goto out;
  489. }
  490. err = check_export(nd.dentry->d_inode, exp.ex_flags,
  491. exp.ex_uuid);
  492. if (err) goto out;
  493. }
  494. expp = svc_export_lookup(&exp);
  495. if (expp)
  496. expp = svc_export_update(&exp, expp);
  497. else
  498. err = -ENOMEM;
  499. cache_flush();
  500. if (expp == NULL)
  501. err = -ENOMEM;
  502. else
  503. exp_put(expp);
  504. out:
  505. nfsd4_fslocs_free(&exp.ex_fslocs);
  506. kfree(exp.ex_uuid);
  507. kfree(exp.ex_path);
  508. if (nd.dentry)
  509. path_release(&nd);
  510. out_no_path:
  511. if (dom)
  512. auth_domain_put(dom);
  513. kfree(buf);
  514. return err;
  515. }
  516. static void exp_flags(struct seq_file *m, int flag, int fsid,
  517. uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs);
  518. static int svc_export_show(struct seq_file *m,
  519. struct cache_detail *cd,
  520. struct cache_head *h)
  521. {
  522. struct svc_export *exp ;
  523. if (h ==NULL) {
  524. seq_puts(m, "#path domain(flags)\n");
  525. return 0;
  526. }
  527. exp = container_of(h, struct svc_export, h);
  528. seq_path(m, exp->ex_mnt, exp->ex_dentry, " \t\n\\");
  529. seq_putc(m, '\t');
  530. seq_escape(m, exp->ex_client->name, " \t\n\\");
  531. seq_putc(m, '(');
  532. if (test_bit(CACHE_VALID, &h->flags) &&
  533. !test_bit(CACHE_NEGATIVE, &h->flags)) {
  534. exp_flags(m, exp->ex_flags, exp->ex_fsid,
  535. exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
  536. if (exp->ex_uuid) {
  537. int i;
  538. seq_puts(m, ",uuid=");
  539. for (i=0; i<16; i++) {
  540. if ((i&3) == 0 && i)
  541. seq_putc(m, ':');
  542. seq_printf(m, "%02x", exp->ex_uuid[i]);
  543. }
  544. }
  545. }
  546. seq_puts(m, ")\n");
  547. return 0;
  548. }
  549. static int svc_export_match(struct cache_head *a, struct cache_head *b)
  550. {
  551. struct svc_export *orig = container_of(a, struct svc_export, h);
  552. struct svc_export *new = container_of(b, struct svc_export, h);
  553. return orig->ex_client == new->ex_client &&
  554. orig->ex_dentry == new->ex_dentry &&
  555. orig->ex_mnt == new->ex_mnt;
  556. }
  557. static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
  558. {
  559. struct svc_export *new = container_of(cnew, struct svc_export, h);
  560. struct svc_export *item = container_of(citem, struct svc_export, h);
  561. kref_get(&item->ex_client->ref);
  562. new->ex_client = item->ex_client;
  563. new->ex_dentry = dget(item->ex_dentry);
  564. new->ex_mnt = mntget(item->ex_mnt);
  565. new->ex_path = NULL;
  566. new->ex_fslocs.locations = NULL;
  567. new->ex_fslocs.locations_count = 0;
  568. new->ex_fslocs.migrated = 0;
  569. }
  570. static void export_update(struct cache_head *cnew, struct cache_head *citem)
  571. {
  572. struct svc_export *new = container_of(cnew, struct svc_export, h);
  573. struct svc_export *item = container_of(citem, struct svc_export, h);
  574. new->ex_flags = item->ex_flags;
  575. new->ex_anon_uid = item->ex_anon_uid;
  576. new->ex_anon_gid = item->ex_anon_gid;
  577. new->ex_fsid = item->ex_fsid;
  578. new->ex_uuid = item->ex_uuid;
  579. item->ex_uuid = NULL;
  580. new->ex_path = item->ex_path;
  581. item->ex_path = NULL;
  582. new->ex_fslocs.locations = item->ex_fslocs.locations;
  583. item->ex_fslocs.locations = NULL;
  584. new->ex_fslocs.locations_count = item->ex_fslocs.locations_count;
  585. item->ex_fslocs.locations_count = 0;
  586. new->ex_fslocs.migrated = item->ex_fslocs.migrated;
  587. item->ex_fslocs.migrated = 0;
  588. }
  589. static struct cache_head *svc_export_alloc(void)
  590. {
  591. struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
  592. if (i)
  593. return &i->h;
  594. else
  595. return NULL;
  596. }
  597. struct cache_detail svc_export_cache = {
  598. .owner = THIS_MODULE,
  599. .hash_size = EXPORT_HASHMAX,
  600. .hash_table = export_table,
  601. .name = "nfsd.export",
  602. .cache_put = svc_export_put,
  603. .cache_request = svc_export_request,
  604. .cache_parse = svc_export_parse,
  605. .cache_show = svc_export_show,
  606. .match = svc_export_match,
  607. .init = svc_export_init,
  608. .update = export_update,
  609. .alloc = svc_export_alloc,
  610. };
  611. static struct svc_export *
  612. svc_export_lookup(struct svc_export *exp)
  613. {
  614. struct cache_head *ch;
  615. int hash;
  616. hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
  617. hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS);
  618. hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS);
  619. ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h,
  620. hash);
  621. if (ch)
  622. return container_of(ch, struct svc_export, h);
  623. else
  624. return NULL;
  625. }
  626. static struct svc_export *
  627. svc_export_update(struct svc_export *new, struct svc_export *old)
  628. {
  629. struct cache_head *ch;
  630. int hash;
  631. hash = hash_ptr(old->ex_client, EXPORT_HASHBITS);
  632. hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS);
  633. hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS);
  634. ch = sunrpc_cache_update(&svc_export_cache, &new->h,
  635. &old->h,
  636. hash);
  637. if (ch)
  638. return container_of(ch, struct svc_export, h);
  639. else
  640. return NULL;
  641. }
  642. static struct svc_expkey *
  643. exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
  644. {
  645. struct svc_expkey key, *ek;
  646. int err;
  647. if (!clp)
  648. return NULL;
  649. key.ek_client = clp;
  650. key.ek_fsidtype = fsid_type;
  651. memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
  652. ek = svc_expkey_lookup(&key);
  653. if (ek != NULL)
  654. if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
  655. ek = ERR_PTR(err);
  656. return ek;
  657. }
  658. static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
  659. struct svc_export *exp)
  660. {
  661. struct svc_expkey key, *ek;
  662. key.ek_client = clp;
  663. key.ek_fsidtype = fsid_type;
  664. memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
  665. key.ek_mnt = exp->ex_mnt;
  666. key.ek_dentry = exp->ex_dentry;
  667. key.h.expiry_time = NEVER;
  668. key.h.flags = 0;
  669. ek = svc_expkey_lookup(&key);
  670. if (ek)
  671. ek = svc_expkey_update(&key,ek);
  672. if (ek) {
  673. cache_put(&ek->h, &svc_expkey_cache);
  674. return 0;
  675. }
  676. return -ENOMEM;
  677. }
  678. /*
  679. * Find the client's export entry matching xdev/xino.
  680. */
  681. static inline struct svc_expkey *
  682. exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
  683. {
  684. u32 fsidv[3];
  685. if (old_valid_dev(dev)) {
  686. mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
  687. return exp_find_key(clp, FSID_DEV, fsidv, NULL);
  688. }
  689. mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
  690. return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
  691. }
  692. /*
  693. * Find the client's export entry matching fsid
  694. */
  695. static inline struct svc_expkey *
  696. exp_get_fsid_key(svc_client *clp, int fsid)
  697. {
  698. u32 fsidv[2];
  699. mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
  700. return exp_find_key(clp, FSID_NUM, fsidv, NULL);
  701. }
  702. svc_export *
  703. exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
  704. struct cache_req *reqp)
  705. {
  706. struct svc_export *exp, key;
  707. if (!clp)
  708. return NULL;
  709. key.ex_client = clp;
  710. key.ex_mnt = mnt;
  711. key.ex_dentry = dentry;
  712. exp = svc_export_lookup(&key);
  713. if (exp != NULL) {
  714. int err;
  715. err = cache_check(&svc_export_cache, &exp->h, reqp);
  716. switch (err) {
  717. case 0: break;
  718. case -EAGAIN:
  719. case -ETIMEDOUT:
  720. exp = ERR_PTR(err);
  721. break;
  722. default:
  723. exp = NULL;
  724. }
  725. }
  726. return exp;
  727. }
  728. /*
  729. * Find the export entry for a given dentry.
  730. */
  731. struct svc_export *
  732. exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
  733. struct cache_req *reqp)
  734. {
  735. svc_export *exp;
  736. dget(dentry);
  737. exp = exp_get_by_name(clp, mnt, dentry, reqp);
  738. while (exp == NULL && !IS_ROOT(dentry)) {
  739. struct dentry *parent;
  740. parent = dget_parent(dentry);
  741. dput(dentry);
  742. dentry = parent;
  743. exp = exp_get_by_name(clp, mnt, dentry, reqp);
  744. }
  745. dput(dentry);
  746. return exp;
  747. }
  748. /*
  749. * Hashtable locking. Write locks are placed only by user processes
  750. * wanting to modify export information.
  751. * Write locking only done in this file. Read locking
  752. * needed externally.
  753. */
  754. static DECLARE_RWSEM(hash_sem);
  755. void
  756. exp_readlock(void)
  757. {
  758. down_read(&hash_sem);
  759. }
  760. static inline void
  761. exp_writelock(void)
  762. {
  763. down_write(&hash_sem);
  764. }
  765. void
  766. exp_readunlock(void)
  767. {
  768. up_read(&hash_sem);
  769. }
  770. static inline void
  771. exp_writeunlock(void)
  772. {
  773. up_write(&hash_sem);
  774. }
  775. static void exp_fsid_unhash(struct svc_export *exp)
  776. {
  777. struct svc_expkey *ek;
  778. if ((exp->ex_flags & NFSEXP_FSID) == 0)
  779. return;
  780. ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
  781. if (ek && !IS_ERR(ek)) {
  782. ek->h.expiry_time = get_seconds()-1;
  783. cache_put(&ek->h, &svc_expkey_cache);
  784. }
  785. svc_expkey_cache.nextcheck = get_seconds();
  786. }
  787. static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
  788. {
  789. u32 fsid[2];
  790. if ((exp->ex_flags & NFSEXP_FSID) == 0)
  791. return 0;
  792. mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
  793. return exp_set_key(clp, FSID_NUM, fsid, exp);
  794. }
  795. static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
  796. {
  797. u32 fsid[2];
  798. struct inode *inode = exp->ex_dentry->d_inode;
  799. dev_t dev = inode->i_sb->s_dev;
  800. if (old_valid_dev(dev)) {
  801. mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
  802. return exp_set_key(clp, FSID_DEV, fsid, exp);
  803. }
  804. mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
  805. return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
  806. }
  807. static void exp_unhash(struct svc_export *exp)
  808. {
  809. struct svc_expkey *ek;
  810. struct inode *inode = exp->ex_dentry->d_inode;
  811. ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
  812. if (ek && !IS_ERR(ek)) {
  813. ek->h.expiry_time = get_seconds()-1;
  814. cache_put(&ek->h, &svc_expkey_cache);
  815. }
  816. svc_expkey_cache.nextcheck = get_seconds();
  817. }
  818. /*
  819. * Export a file system.
  820. */
  821. int
  822. exp_export(struct nfsctl_export *nxp)
  823. {
  824. svc_client *clp;
  825. struct svc_export *exp = NULL;
  826. struct svc_export new;
  827. struct svc_expkey *fsid_key = NULL;
  828. struct nameidata nd;
  829. int err;
  830. /* Consistency check */
  831. err = -EINVAL;
  832. if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
  833. !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
  834. goto out;
  835. dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
  836. nxp->ex_client, nxp->ex_path,
  837. (unsigned)nxp->ex_dev, (long)nxp->ex_ino,
  838. nxp->ex_flags);
  839. /* Try to lock the export table for update */
  840. exp_writelock();
  841. /* Look up client info */
  842. if (!(clp = auth_domain_find(nxp->ex_client)))
  843. goto out_unlock;
  844. /* Look up the dentry */
  845. err = path_lookup(nxp->ex_path, 0, &nd);
  846. if (err)
  847. goto out_unlock;
  848. err = -EINVAL;
  849. exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
  850. memset(&new, 0, sizeof(new));
  851. /* must make sure there won't be an ex_fsid clash */
  852. if ((nxp->ex_flags & NFSEXP_FSID) &&
  853. (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
  854. !IS_ERR(fsid_key) &&
  855. fsid_key->ek_mnt &&
  856. (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
  857. goto finish;
  858. if (exp) {
  859. /* just a flags/id/fsid update */
  860. exp_fsid_unhash(exp);
  861. exp->ex_flags = nxp->ex_flags;
  862. exp->ex_anon_uid = nxp->ex_anon_uid;
  863. exp->ex_anon_gid = nxp->ex_anon_gid;
  864. exp->ex_fsid = nxp->ex_dev;
  865. err = exp_fsid_hash(clp, exp);
  866. goto finish;
  867. }
  868. err = check_export(nd.dentry->d_inode, nxp->ex_flags, NULL);
  869. if (err) goto finish;
  870. err = -ENOMEM;
  871. dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
  872. new.h.expiry_time = NEVER;
  873. new.h.flags = 0;
  874. new.ex_path = kstrdup(nxp->ex_path, GFP_KERNEL);
  875. if (!new.ex_path)
  876. goto finish;
  877. new.ex_client = clp;
  878. new.ex_mnt = nd.mnt;
  879. new.ex_dentry = nd.dentry;
  880. new.ex_flags = nxp->ex_flags;
  881. new.ex_anon_uid = nxp->ex_anon_uid;
  882. new.ex_anon_gid = nxp->ex_anon_gid;
  883. new.ex_fsid = nxp->ex_dev;
  884. exp = svc_export_lookup(&new);
  885. if (exp)
  886. exp = svc_export_update(&new, exp);
  887. if (!exp)
  888. goto finish;
  889. if (exp_hash(clp, exp) ||
  890. exp_fsid_hash(clp, exp)) {
  891. /* failed to create at least one index */
  892. exp_do_unexport(exp);
  893. cache_flush();
  894. } else
  895. err = 0;
  896. finish:
  897. if (new.ex_path)
  898. kfree(new.ex_path);
  899. if (exp)
  900. exp_put(exp);
  901. if (fsid_key && !IS_ERR(fsid_key))
  902. cache_put(&fsid_key->h, &svc_expkey_cache);
  903. if (clp)
  904. auth_domain_put(clp);
  905. path_release(&nd);
  906. out_unlock:
  907. exp_writeunlock();
  908. out:
  909. return err;
  910. }
  911. /*
  912. * Unexport a file system. The export entry has already
  913. * been removed from the client's list of exported fs's.
  914. */
  915. static void
  916. exp_do_unexport(svc_export *unexp)
  917. {
  918. unexp->h.expiry_time = get_seconds()-1;
  919. svc_export_cache.nextcheck = get_seconds();
  920. exp_unhash(unexp);
  921. exp_fsid_unhash(unexp);
  922. }
  923. /*
  924. * unexport syscall.
  925. */
  926. int
  927. exp_unexport(struct nfsctl_export *nxp)
  928. {
  929. struct auth_domain *dom;
  930. svc_export *exp;
  931. struct nameidata nd;
  932. int err;
  933. /* Consistency check */
  934. if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
  935. !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
  936. return -EINVAL;
  937. exp_writelock();
  938. err = -EINVAL;
  939. dom = auth_domain_find(nxp->ex_client);
  940. if (!dom) {
  941. dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
  942. goto out_unlock;
  943. }
  944. err = path_lookup(nxp->ex_path, 0, &nd);
  945. if (err)
  946. goto out_domain;
  947. err = -EINVAL;
  948. exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
  949. path_release(&nd);
  950. if (!exp)
  951. goto out_domain;
  952. exp_do_unexport(exp);
  953. exp_put(exp);
  954. err = 0;
  955. out_domain:
  956. auth_domain_put(dom);
  957. cache_flush();
  958. out_unlock:
  959. exp_writeunlock();
  960. return err;
  961. }
  962. /*
  963. * Obtain the root fh on behalf of a client.
  964. * This could be done in user space, but I feel that it adds some safety
  965. * since its harder to fool a kernel module than a user space program.
  966. */
  967. int
  968. exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
  969. {
  970. struct svc_export *exp;
  971. struct nameidata nd;
  972. struct inode *inode;
  973. struct svc_fh fh;
  974. int err;
  975. err = -EPERM;
  976. /* NB: we probably ought to check that it's NUL-terminated */
  977. if (path_lookup(path, 0, &nd)) {
  978. printk("nfsd: exp_rootfh path not found %s", path);
  979. return err;
  980. }
  981. inode = nd.dentry->d_inode;
  982. dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
  983. path, nd.dentry, clp->name,
  984. inode->i_sb->s_id, inode->i_ino);
  985. exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
  986. if (IS_ERR(exp)) {
  987. err = PTR_ERR(exp);
  988. goto out;
  989. }
  990. if (!exp) {
  991. dprintk("nfsd: exp_rootfh export not found.\n");
  992. goto out;
  993. }
  994. /*
  995. * fh must be initialized before calling fh_compose
  996. */
  997. fh_init(&fh, maxsize);
  998. if (fh_compose(&fh, exp, nd.dentry, NULL))
  999. err = -EINVAL;
  1000. else
  1001. err = 0;
  1002. memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
  1003. fh_put(&fh);
  1004. exp_put(exp);
  1005. out:
  1006. path_release(&nd);
  1007. return err;
  1008. }
  1009. struct svc_export *
  1010. exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
  1011. struct cache_req *reqp)
  1012. {
  1013. struct svc_export *exp;
  1014. struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
  1015. if (!ek || IS_ERR(ek))
  1016. return ERR_PTR(PTR_ERR(ek));
  1017. exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
  1018. cache_put(&ek->h, &svc_expkey_cache);
  1019. if (!exp || IS_ERR(exp))
  1020. return ERR_PTR(PTR_ERR(exp));
  1021. return exp;
  1022. }
  1023. /*
  1024. * Called when we need the filehandle for the root of the pseudofs,
  1025. * for a given NFSv4 client. The root is defined to be the
  1026. * export point with fsid==0
  1027. */
  1028. __be32
  1029. exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
  1030. struct cache_req *creq)
  1031. {
  1032. struct svc_export *exp;
  1033. __be32 rv;
  1034. u32 fsidv[2];
  1035. mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
  1036. exp = exp_find(clp, FSID_NUM, fsidv, creq);
  1037. if (IS_ERR(exp))
  1038. return nfserrno(PTR_ERR(exp));
  1039. if (exp == NULL)
  1040. return nfserr_perm;
  1041. rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
  1042. exp_put(exp);
  1043. return rv;
  1044. }
  1045. /* Iterator */
  1046. static void *e_start(struct seq_file *m, loff_t *pos)
  1047. __acquires(svc_export_cache.hash_lock)
  1048. {
  1049. loff_t n = *pos;
  1050. unsigned hash, export;
  1051. struct cache_head *ch;
  1052. exp_readlock();
  1053. read_lock(&svc_export_cache.hash_lock);
  1054. if (!n--)
  1055. return SEQ_START_TOKEN;
  1056. hash = n >> 32;
  1057. export = n & ((1LL<<32) - 1);
  1058. for (ch=export_table[hash]; ch; ch=ch->next)
  1059. if (!export--)
  1060. return ch;
  1061. n &= ~((1LL<<32) - 1);
  1062. do {
  1063. hash++;
  1064. n += 1LL<<32;
  1065. } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL);
  1066. if (hash >= EXPORT_HASHMAX)
  1067. return NULL;
  1068. *pos = n+1;
  1069. return export_table[hash];
  1070. }
  1071. static void *e_next(struct seq_file *m, void *p, loff_t *pos)
  1072. {
  1073. struct cache_head *ch = p;
  1074. int hash = (*pos >> 32);
  1075. if (p == SEQ_START_TOKEN)
  1076. hash = 0;
  1077. else if (ch->next == NULL) {
  1078. hash++;
  1079. *pos += 1LL<<32;
  1080. } else {
  1081. ++*pos;
  1082. return ch->next;
  1083. }
  1084. *pos &= ~((1LL<<32) - 1);
  1085. while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) {
  1086. hash++;
  1087. *pos += 1LL<<32;
  1088. }
  1089. if (hash >= EXPORT_HASHMAX)
  1090. return NULL;
  1091. ++*pos;
  1092. return export_table[hash];
  1093. }
  1094. static void e_stop(struct seq_file *m, void *p)
  1095. __releases(svc_export_cache.hash_lock)
  1096. {
  1097. read_unlock(&svc_export_cache.hash_lock);
  1098. exp_readunlock();
  1099. }
  1100. static struct flags {
  1101. int flag;
  1102. char *name[2];
  1103. } expflags[] = {
  1104. { NFSEXP_READONLY, {"ro", "rw"}},
  1105. { NFSEXP_INSECURE_PORT, {"insecure", ""}},
  1106. { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
  1107. { NFSEXP_ALLSQUASH, {"all_squash", ""}},
  1108. { NFSEXP_ASYNC, {"async", "sync"}},
  1109. { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
  1110. { NFSEXP_NOHIDE, {"nohide", ""}},
  1111. { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
  1112. { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
  1113. { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
  1114. #ifdef MSNFS
  1115. { NFSEXP_MSNFS, {"msnfs", ""}},
  1116. #endif
  1117. { 0, {"", ""}}
  1118. };
  1119. static void exp_flags(struct seq_file *m, int flag, int fsid,
  1120. uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
  1121. {
  1122. int first = 0;
  1123. struct flags *flg;
  1124. for (flg = expflags; flg->flag; flg++) {
  1125. int state = (flg->flag & flag)?0:1;
  1126. if (*flg->name[state])
  1127. seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
  1128. }
  1129. if (flag & NFSEXP_FSID)
  1130. seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
  1131. if (anonu != (uid_t)-2 && anonu != (0x10000-2))
  1132. seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
  1133. if (anong != (gid_t)-2 && anong != (0x10000-2))
  1134. seq_printf(m, "%sanongid=%d", first++?",":"", anong);
  1135. if (fsloc && fsloc->locations_count > 0) {
  1136. char *loctype = (fsloc->migrated) ? "refer" : "replicas";
  1137. int i;
  1138. seq_printf(m, "%s%s=", first++?",":"", loctype);
  1139. seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
  1140. seq_putc(m, '@');
  1141. seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
  1142. for (i = 1; i < fsloc->locations_count; i++) {
  1143. seq_putc(m, ';');
  1144. seq_escape(m, fsloc->locations[i].path, ",;@ \t\n\\");
  1145. seq_putc(m, '@');
  1146. seq_escape(m, fsloc->locations[i].hosts, ",;@ \t\n\\");
  1147. }
  1148. }
  1149. }
  1150. static int e_show(struct seq_file *m, void *p)
  1151. {
  1152. struct cache_head *cp = p;
  1153. struct svc_export *exp = container_of(cp, struct svc_export, h);
  1154. if (p == SEQ_START_TOKEN) {
  1155. seq_puts(m, "# Version 1.1\n");
  1156. seq_puts(m, "# Path Client(Flags) # IPs\n");
  1157. return 0;
  1158. }
  1159. cache_get(&exp->h);
  1160. if (cache_check(&svc_export_cache, &exp->h, NULL))
  1161. return 0;
  1162. cache_put(&exp->h, &svc_export_cache);
  1163. return svc_export_show(m, &svc_export_cache, cp);
  1164. }
  1165. struct seq_operations nfs_exports_op = {
  1166. .start = e_start,
  1167. .next = e_next,
  1168. .stop = e_stop,
  1169. .show = e_show,
  1170. };
  1171. /*
  1172. * Add or modify a client.
  1173. * Change requests may involve the list of host addresses. The list of
  1174. * exports and possibly existing uid maps are left untouched.
  1175. */
  1176. int
  1177. exp_addclient(struct nfsctl_client *ncp)
  1178. {
  1179. struct auth_domain *dom;
  1180. int i, err;
  1181. /* First, consistency check. */
  1182. err = -EINVAL;
  1183. if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
  1184. goto out;
  1185. if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
  1186. goto out;
  1187. /* Lock the hashtable */
  1188. exp_writelock();
  1189. dom = unix_domain_find(ncp->cl_ident);
  1190. err = -ENOMEM;
  1191. if (!dom)
  1192. goto out_unlock;
  1193. /* Insert client into hashtable. */
  1194. for (i = 0; i < ncp->cl_naddr; i++)
  1195. auth_unix_add_addr(ncp->cl_addrlist[i], dom);
  1196. auth_unix_forget_old(dom);
  1197. auth_domain_put(dom);
  1198. err = 0;
  1199. out_unlock:
  1200. exp_writeunlock();
  1201. out:
  1202. return err;
  1203. }
  1204. /*
  1205. * Delete a client given an identifier.
  1206. */
  1207. int
  1208. exp_delclient(struct nfsctl_client *ncp)
  1209. {
  1210. int err;
  1211. struct auth_domain *dom;
  1212. err = -EINVAL;
  1213. if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
  1214. goto out;
  1215. /* Lock the hashtable */
  1216. exp_writelock();
  1217. dom = auth_domain_find(ncp->cl_ident);
  1218. /* just make sure that no addresses work
  1219. * and that it will expire soon
  1220. */
  1221. if (dom) {
  1222. err = auth_unix_forget_old(dom);
  1223. auth_domain_put(dom);
  1224. }
  1225. exp_writeunlock();
  1226. out:
  1227. return err;
  1228. }
  1229. /*
  1230. * Verify that string is non-empty and does not exceed max length.
  1231. */
  1232. static int
  1233. exp_verify_string(char *cp, int max)
  1234. {
  1235. int i;
  1236. for (i = 0; i < max; i++)
  1237. if (!cp[i])
  1238. return i;
  1239. cp[i] = 0;
  1240. printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
  1241. return 0;
  1242. }
  1243. /*
  1244. * Initialize the exports module.
  1245. */
  1246. void
  1247. nfsd_export_init(void)
  1248. {
  1249. dprintk("nfsd: initializing export module.\n");
  1250. cache_register(&svc_export_cache);
  1251. cache_register(&svc_expkey_cache);
  1252. }
  1253. /*
  1254. * Flush exports table - called when last nfsd thread is killed
  1255. */
  1256. void
  1257. nfsd_export_flush(void)
  1258. {
  1259. exp_writelock();
  1260. cache_purge(&svc_expkey_cache);
  1261. cache_purge(&svc_export_cache);
  1262. exp_writeunlock();
  1263. }
  1264. /*
  1265. * Shutdown the exports module.
  1266. */
  1267. void
  1268. nfsd_export_shutdown(void)
  1269. {
  1270. dprintk("nfsd: shutting down export module.\n");
  1271. exp_writelock();
  1272. if (cache_unregister(&svc_expkey_cache))
  1273. printk(KERN_ERR "nfsd: failed to unregister expkey cache\n");
  1274. if (cache_unregister(&svc_export_cache))
  1275. printk(KERN_ERR "nfsd: failed to unregister export cache\n");
  1276. svcauth_unix_purge();
  1277. exp_writeunlock();
  1278. dprintk("nfsd: export shutdown complete.\n");
  1279. }