nfsctl.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501
  1. /*
  2. * Syscall interface to knfsd.
  3. *
  4. * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  5. */
  6. #include <linux/slab.h>
  7. #include <linux/namei.h>
  8. #include <linux/ctype.h>
  9. #include <linux/sunrpc/svcsock.h>
  10. #include <linux/nfsd/syscall.h>
  11. #include <linux/lockd/lockd.h>
  12. #include <linux/sunrpc/clnt.h>
  13. #include "idmap.h"
  14. #include "nfsd.h"
  15. #include "cache.h"
  16. /*
  17. * We have a single directory with 9 nodes in it.
  18. */
  19. enum {
  20. NFSD_Root = 1,
  21. #ifdef CONFIG_NFSD_DEPRECATED
  22. NFSD_Svc,
  23. NFSD_Add,
  24. NFSD_Del,
  25. NFSD_Export,
  26. NFSD_Unexport,
  27. NFSD_Getfd,
  28. NFSD_Getfs,
  29. #endif
  30. NFSD_List,
  31. NFSD_Export_features,
  32. NFSD_Fh,
  33. NFSD_FO_UnlockIP,
  34. NFSD_FO_UnlockFS,
  35. NFSD_Threads,
  36. NFSD_Pool_Threads,
  37. NFSD_Pool_Stats,
  38. NFSD_Versions,
  39. NFSD_Ports,
  40. NFSD_MaxBlkSize,
  41. /*
  42. * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
  43. * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
  44. */
  45. #ifdef CONFIG_NFSD_V4
  46. NFSD_Leasetime,
  47. NFSD_Gracetime,
  48. NFSD_RecoveryDir,
  49. #endif
  50. };
  51. /*
  52. * write() for these nodes.
  53. */
  54. #ifdef CONFIG_NFSD_DEPRECATED
  55. static ssize_t write_svc(struct file *file, char *buf, size_t size);
  56. static ssize_t write_add(struct file *file, char *buf, size_t size);
  57. static ssize_t write_del(struct file *file, char *buf, size_t size);
  58. static ssize_t write_export(struct file *file, char *buf, size_t size);
  59. static ssize_t write_unexport(struct file *file, char *buf, size_t size);
  60. static ssize_t write_getfd(struct file *file, char *buf, size_t size);
  61. static ssize_t write_getfs(struct file *file, char *buf, size_t size);
  62. #endif
  63. static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
  64. static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
  65. static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
  66. static ssize_t write_threads(struct file *file, char *buf, size_t size);
  67. static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
  68. static ssize_t write_versions(struct file *file, char *buf, size_t size);
  69. static ssize_t write_ports(struct file *file, char *buf, size_t size);
  70. static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
  71. #ifdef CONFIG_NFSD_V4
  72. static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
  73. static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
  74. static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
  75. #endif
  76. static ssize_t (*write_op[])(struct file *, char *, size_t) = {
  77. #ifdef CONFIG_NFSD_DEPRECATED
  78. [NFSD_Svc] = write_svc,
  79. [NFSD_Add] = write_add,
  80. [NFSD_Del] = write_del,
  81. [NFSD_Export] = write_export,
  82. [NFSD_Unexport] = write_unexport,
  83. [NFSD_Getfd] = write_getfd,
  84. [NFSD_Getfs] = write_getfs,
  85. #endif
  86. [NFSD_Fh] = write_filehandle,
  87. [NFSD_FO_UnlockIP] = write_unlock_ip,
  88. [NFSD_FO_UnlockFS] = write_unlock_fs,
  89. [NFSD_Threads] = write_threads,
  90. [NFSD_Pool_Threads] = write_pool_threads,
  91. [NFSD_Versions] = write_versions,
  92. [NFSD_Ports] = write_ports,
  93. [NFSD_MaxBlkSize] = write_maxblksize,
  94. #ifdef CONFIG_NFSD_V4
  95. [NFSD_Leasetime] = write_leasetime,
  96. [NFSD_Gracetime] = write_gracetime,
  97. [NFSD_RecoveryDir] = write_recoverydir,
  98. #endif
  99. };
  100. static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
  101. {
  102. ino_t ino = file->f_path.dentry->d_inode->i_ino;
  103. char *data;
  104. ssize_t rv;
  105. if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
  106. return -EINVAL;
  107. data = simple_transaction_get(file, buf, size);
  108. if (IS_ERR(data))
  109. return PTR_ERR(data);
  110. rv = write_op[ino](file, data, size);
  111. if (rv >= 0) {
  112. simple_transaction_set(file, rv);
  113. rv = size;
  114. }
  115. return rv;
  116. }
  117. static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
  118. {
  119. #ifdef CONFIG_NFSD_DEPRECATED
  120. static int warned;
  121. if (file->f_dentry->d_name.name[0] == '.' && !warned) {
  122. printk(KERN_INFO
  123. "Warning: \"%s\" uses deprecated NFSD interface: %s."
  124. " This will be removed in 2.6.40\n",
  125. current->comm, file->f_dentry->d_name.name);
  126. warned = 1;
  127. }
  128. #endif
  129. if (! file->private_data) {
  130. /* An attempt to read a transaction file without writing
  131. * causes a 0-byte write so that the file can return
  132. * state information
  133. */
  134. ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
  135. if (rv < 0)
  136. return rv;
  137. }
  138. return simple_transaction_read(file, buf, size, pos);
  139. }
  140. static const struct file_operations transaction_ops = {
  141. .write = nfsctl_transaction_write,
  142. .read = nfsctl_transaction_read,
  143. .release = simple_transaction_release,
  144. .llseek = default_llseek,
  145. };
  146. static int exports_open(struct inode *inode, struct file *file)
  147. {
  148. return seq_open(file, &nfs_exports_op);
  149. }
  150. static const struct file_operations exports_operations = {
  151. .open = exports_open,
  152. .read = seq_read,
  153. .llseek = seq_lseek,
  154. .release = seq_release,
  155. .owner = THIS_MODULE,
  156. };
  157. static int export_features_show(struct seq_file *m, void *v)
  158. {
  159. seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
  160. return 0;
  161. }
  162. static int export_features_open(struct inode *inode, struct file *file)
  163. {
  164. return single_open(file, export_features_show, NULL);
  165. }
  166. static struct file_operations export_features_operations = {
  167. .open = export_features_open,
  168. .read = seq_read,
  169. .llseek = seq_lseek,
  170. .release = single_release,
  171. };
  172. extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
  173. extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
  174. static const struct file_operations pool_stats_operations = {
  175. .open = nfsd_pool_stats_open,
  176. .read = seq_read,
  177. .llseek = seq_lseek,
  178. .release = nfsd_pool_stats_release,
  179. .owner = THIS_MODULE,
  180. };
  181. /*----------------------------------------------------------------------------*/
  182. /*
  183. * payload - write methods
  184. */
  185. #ifdef CONFIG_NFSD_DEPRECATED
  186. /**
  187. * write_svc - Start kernel's NFSD server
  188. *
  189. * Deprecated. /proc/fs/nfsd/threads is preferred.
  190. * Function remains to support old versions of nfs-utils.
  191. *
  192. * Input:
  193. * buf: struct nfsctl_svc
  194. * svc_port: port number of this
  195. * server's listener
  196. * svc_nthreads: number of threads to start
  197. * size: size in bytes of passed in nfsctl_svc
  198. * Output:
  199. * On success: returns zero
  200. * On error: return code is negative errno value
  201. */
  202. static ssize_t write_svc(struct file *file, char *buf, size_t size)
  203. {
  204. struct nfsctl_svc *data;
  205. int err;
  206. if (size < sizeof(*data))
  207. return -EINVAL;
  208. data = (struct nfsctl_svc*) buf;
  209. err = nfsd_svc(data->svc_port, data->svc_nthreads);
  210. if (err < 0)
  211. return err;
  212. return 0;
  213. }
  214. /**
  215. * write_add - Add or modify client entry in auth unix cache
  216. *
  217. * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
  218. * Function remains to support old versions of nfs-utils.
  219. *
  220. * Input:
  221. * buf: struct nfsctl_client
  222. * cl_ident: '\0'-terminated C string
  223. * containing domain name
  224. * of client
  225. * cl_naddr: no. of items in cl_addrlist
  226. * cl_addrlist: array of client addresses
  227. * cl_fhkeytype: ignored
  228. * cl_fhkeylen: ignored
  229. * cl_fhkey: ignored
  230. * size: size in bytes of passed in nfsctl_client
  231. * Output:
  232. * On success: returns zero
  233. * On error: return code is negative errno value
  234. *
  235. * Note: Only AF_INET client addresses are passed in, since
  236. * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
  237. */
  238. static ssize_t write_add(struct file *file, char *buf, size_t size)
  239. {
  240. struct nfsctl_client *data;
  241. if (size < sizeof(*data))
  242. return -EINVAL;
  243. data = (struct nfsctl_client *)buf;
  244. return exp_addclient(data);
  245. }
  246. /**
  247. * write_del - Remove client from auth unix cache
  248. *
  249. * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
  250. * Function remains to support old versions of nfs-utils.
  251. *
  252. * Input:
  253. * buf: struct nfsctl_client
  254. * cl_ident: '\0'-terminated C string
  255. * containing domain name
  256. * of client
  257. * cl_naddr: ignored
  258. * cl_addrlist: ignored
  259. * cl_fhkeytype: ignored
  260. * cl_fhkeylen: ignored
  261. * cl_fhkey: ignored
  262. * size: size in bytes of passed in nfsctl_client
  263. * Output:
  264. * On success: returns zero
  265. * On error: return code is negative errno value
  266. *
  267. * Note: Only AF_INET client addresses are passed in, since
  268. * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
  269. */
  270. static ssize_t write_del(struct file *file, char *buf, size_t size)
  271. {
  272. struct nfsctl_client *data;
  273. if (size < sizeof(*data))
  274. return -EINVAL;
  275. data = (struct nfsctl_client *)buf;
  276. return exp_delclient(data);
  277. }
  278. /**
  279. * write_export - Export part or all of a local file system
  280. *
  281. * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
  282. * Function remains to support old versions of nfs-utils.
  283. *
  284. * Input:
  285. * buf: struct nfsctl_export
  286. * ex_client: '\0'-terminated C string
  287. * containing domain name
  288. * of client allowed to access
  289. * this export
  290. * ex_path: '\0'-terminated C string
  291. * containing pathname of
  292. * directory in local file system
  293. * ex_dev: fsid to use for this export
  294. * ex_ino: ignored
  295. * ex_flags: export flags for this export
  296. * ex_anon_uid: UID to use for anonymous
  297. * requests
  298. * ex_anon_gid: GID to use for anonymous
  299. * requests
  300. * size: size in bytes of passed in nfsctl_export
  301. * Output:
  302. * On success: returns zero
  303. * On error: return code is negative errno value
  304. */
  305. static ssize_t write_export(struct file *file, char *buf, size_t size)
  306. {
  307. struct nfsctl_export *data;
  308. if (size < sizeof(*data))
  309. return -EINVAL;
  310. data = (struct nfsctl_export*)buf;
  311. return exp_export(data);
  312. }
  313. /**
  314. * write_unexport - Unexport a previously exported file system
  315. *
  316. * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
  317. * Function remains to support old versions of nfs-utils.
  318. *
  319. * Input:
  320. * buf: struct nfsctl_export
  321. * ex_client: '\0'-terminated C string
  322. * containing domain name
  323. * of client no longer allowed
  324. * to access this export
  325. * ex_path: '\0'-terminated C string
  326. * containing pathname of
  327. * directory in local file system
  328. * ex_dev: ignored
  329. * ex_ino: ignored
  330. * ex_flags: ignored
  331. * ex_anon_uid: ignored
  332. * ex_anon_gid: ignored
  333. * size: size in bytes of passed in nfsctl_export
  334. * Output:
  335. * On success: returns zero
  336. * On error: return code is negative errno value
  337. */
  338. static ssize_t write_unexport(struct file *file, char *buf, size_t size)
  339. {
  340. struct nfsctl_export *data;
  341. if (size < sizeof(*data))
  342. return -EINVAL;
  343. data = (struct nfsctl_export*)buf;
  344. return exp_unexport(data);
  345. }
  346. /**
  347. * write_getfs - Get a variable-length NFS file handle by path
  348. *
  349. * Deprecated. /proc/fs/nfsd/filehandle is preferred.
  350. * Function remains to support old versions of nfs-utils.
  351. *
  352. * Input:
  353. * buf: struct nfsctl_fsparm
  354. * gd_addr: socket address of client
  355. * gd_path: '\0'-terminated C string
  356. * containing pathname of
  357. * directory in local file system
  358. * gd_maxlen: maximum size of returned file
  359. * handle
  360. * size: size in bytes of passed in nfsctl_fsparm
  361. * Output:
  362. * On success: passed-in buffer filled with a knfsd_fh structure
  363. * (a variable-length raw NFS file handle);
  364. * return code is the size in bytes of the file handle
  365. * On error: return code is negative errno value
  366. *
  367. * Note: Only AF_INET client addresses are passed in, since gd_addr
  368. * is the same size as a struct sockaddr_in.
  369. */
  370. static ssize_t write_getfs(struct file *file, char *buf, size_t size)
  371. {
  372. struct nfsctl_fsparm *data;
  373. struct sockaddr_in *sin;
  374. struct auth_domain *clp;
  375. int err = 0;
  376. struct knfsd_fh *res;
  377. struct in6_addr in6;
  378. if (size < sizeof(*data))
  379. return -EINVAL;
  380. data = (struct nfsctl_fsparm*)buf;
  381. err = -EPROTONOSUPPORT;
  382. if (data->gd_addr.sa_family != AF_INET)
  383. goto out;
  384. sin = (struct sockaddr_in *)&data->gd_addr;
  385. if (data->gd_maxlen > NFS3_FHSIZE)
  386. data->gd_maxlen = NFS3_FHSIZE;
  387. res = (struct knfsd_fh*)buf;
  388. exp_readlock();
  389. ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
  390. clp = auth_unix_lookup(&init_net, &in6);
  391. if (!clp)
  392. err = -EPERM;
  393. else {
  394. err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
  395. auth_domain_put(clp);
  396. }
  397. exp_readunlock();
  398. if (err == 0)
  399. err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
  400. out:
  401. return err;
  402. }
  403. /**
  404. * write_getfd - Get a fixed-length NFS file handle by path (used by mountd)
  405. *
  406. * Deprecated. /proc/fs/nfsd/filehandle is preferred.
  407. * Function remains to support old versions of nfs-utils.
  408. *
  409. * Input:
  410. * buf: struct nfsctl_fdparm
  411. * gd_addr: socket address of client
  412. * gd_path: '\0'-terminated C string
  413. * containing pathname of
  414. * directory in local file system
  415. * gd_version: fdparm structure version
  416. * size: size in bytes of passed in nfsctl_fdparm
  417. * Output:
  418. * On success: passed-in buffer filled with nfsctl_res
  419. * (a fixed-length raw NFS file handle);
  420. * return code is the size in bytes of the file handle
  421. * On error: return code is negative errno value
  422. *
  423. * Note: Only AF_INET client addresses are passed in, since gd_addr
  424. * is the same size as a struct sockaddr_in.
  425. */
  426. static ssize_t write_getfd(struct file *file, char *buf, size_t size)
  427. {
  428. struct nfsctl_fdparm *data;
  429. struct sockaddr_in *sin;
  430. struct auth_domain *clp;
  431. int err = 0;
  432. struct knfsd_fh fh;
  433. char *res;
  434. struct in6_addr in6;
  435. if (size < sizeof(*data))
  436. return -EINVAL;
  437. data = (struct nfsctl_fdparm*)buf;
  438. err = -EPROTONOSUPPORT;
  439. if (data->gd_addr.sa_family != AF_INET)
  440. goto out;
  441. err = -EINVAL;
  442. if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
  443. goto out;
  444. res = buf;
  445. sin = (struct sockaddr_in *)&data->gd_addr;
  446. exp_readlock();
  447. ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
  448. clp = auth_unix_lookup(&init_net, &in6);
  449. if (!clp)
  450. err = -EPERM;
  451. else {
  452. err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
  453. auth_domain_put(clp);
  454. }
  455. exp_readunlock();
  456. if (err == 0) {
  457. memset(res,0, NFS_FHSIZE);
  458. memcpy(res, &fh.fh_base, fh.fh_size);
  459. err = NFS_FHSIZE;
  460. }
  461. out:
  462. return err;
  463. }
  464. #endif /* CONFIG_NFSD_DEPRECATED */
  465. /**
  466. * write_unlock_ip - Release all locks used by a client
  467. *
  468. * Experimental.
  469. *
  470. * Input:
  471. * buf: '\n'-terminated C string containing a
  472. * presentation format IP address
  473. * size: length of C string in @buf
  474. * Output:
  475. * On success: returns zero if all specified locks were released;
  476. * returns one if one or more locks were not released
  477. * On error: return code is negative errno value
  478. */
  479. static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
  480. {
  481. struct sockaddr_storage address;
  482. struct sockaddr *sap = (struct sockaddr *)&address;
  483. size_t salen = sizeof(address);
  484. char *fo_path;
  485. /* sanity check */
  486. if (size == 0)
  487. return -EINVAL;
  488. if (buf[size-1] != '\n')
  489. return -EINVAL;
  490. fo_path = buf;
  491. if (qword_get(&buf, fo_path, size) < 0)
  492. return -EINVAL;
  493. if (rpc_pton(fo_path, size, sap, salen) == 0)
  494. return -EINVAL;
  495. return nlmsvc_unlock_all_by_ip(sap);
  496. }
  497. /**
  498. * write_unlock_fs - Release all locks on a local file system
  499. *
  500. * Experimental.
  501. *
  502. * Input:
  503. * buf: '\n'-terminated C string containing the
  504. * absolute pathname of a local file system
  505. * size: length of C string in @buf
  506. * Output:
  507. * On success: returns zero if all specified locks were released;
  508. * returns one if one or more locks were not released
  509. * On error: return code is negative errno value
  510. */
  511. static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
  512. {
  513. struct path path;
  514. char *fo_path;
  515. int error;
  516. /* sanity check */
  517. if (size == 0)
  518. return -EINVAL;
  519. if (buf[size-1] != '\n')
  520. return -EINVAL;
  521. fo_path = buf;
  522. if (qword_get(&buf, fo_path, size) < 0)
  523. return -EINVAL;
  524. error = kern_path(fo_path, 0, &path);
  525. if (error)
  526. return error;
  527. /*
  528. * XXX: Needs better sanity checking. Otherwise we could end up
  529. * releasing locks on the wrong file system.
  530. *
  531. * For example:
  532. * 1. Does the path refer to a directory?
  533. * 2. Is that directory a mount point, or
  534. * 3. Is that directory the root of an exported file system?
  535. */
  536. error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb);
  537. path_put(&path);
  538. return error;
  539. }
  540. /**
  541. * write_filehandle - Get a variable-length NFS file handle by path
  542. *
  543. * On input, the buffer contains a '\n'-terminated C string comprised of
  544. * three alphanumeric words separated by whitespace. The string may
  545. * contain escape sequences.
  546. *
  547. * Input:
  548. * buf:
  549. * domain: client domain name
  550. * path: export pathname
  551. * maxsize: numeric maximum size of
  552. * @buf
  553. * size: length of C string in @buf
  554. * Output:
  555. * On success: passed-in buffer filled with '\n'-terminated C
  556. * string containing a ASCII hex text version
  557. * of the NFS file handle;
  558. * return code is the size in bytes of the string
  559. * On error: return code is negative errno value
  560. */
  561. static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
  562. {
  563. char *dname, *path;
  564. int uninitialized_var(maxsize);
  565. char *mesg = buf;
  566. int len;
  567. struct auth_domain *dom;
  568. struct knfsd_fh fh;
  569. if (size == 0)
  570. return -EINVAL;
  571. if (buf[size-1] != '\n')
  572. return -EINVAL;
  573. buf[size-1] = 0;
  574. dname = mesg;
  575. len = qword_get(&mesg, dname, size);
  576. if (len <= 0)
  577. return -EINVAL;
  578. path = dname+len+1;
  579. len = qword_get(&mesg, path, size);
  580. if (len <= 0)
  581. return -EINVAL;
  582. len = get_int(&mesg, &maxsize);
  583. if (len)
  584. return len;
  585. if (maxsize < NFS_FHSIZE)
  586. return -EINVAL;
  587. if (maxsize > NFS3_FHSIZE)
  588. maxsize = NFS3_FHSIZE;
  589. if (qword_get(&mesg, mesg, size)>0)
  590. return -EINVAL;
  591. /* we have all the words, they are in buf.. */
  592. dom = unix_domain_find(dname);
  593. if (!dom)
  594. return -ENOMEM;
  595. len = exp_rootfh(dom, path, &fh, maxsize);
  596. auth_domain_put(dom);
  597. if (len)
  598. return len;
  599. mesg = buf;
  600. len = SIMPLE_TRANSACTION_LIMIT;
  601. qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
  602. mesg[-1] = '\n';
  603. return mesg - buf;
  604. }
  605. /**
  606. * write_threads - Start NFSD, or report the current number of running threads
  607. *
  608. * Input:
  609. * buf: ignored
  610. * size: zero
  611. * Output:
  612. * On success: passed-in buffer filled with '\n'-terminated C
  613. * string numeric value representing the number of
  614. * running NFSD threads;
  615. * return code is the size in bytes of the string
  616. * On error: return code is zero
  617. *
  618. * OR
  619. *
  620. * Input:
  621. * buf: C string containing an unsigned
  622. * integer value representing the
  623. * number of NFSD threads to start
  624. * size: non-zero length of C string in @buf
  625. * Output:
  626. * On success: NFS service is started;
  627. * passed-in buffer filled with '\n'-terminated C
  628. * string numeric value representing the number of
  629. * running NFSD threads;
  630. * return code is the size in bytes of the string
  631. * On error: return code is zero or a negative errno value
  632. */
  633. static ssize_t write_threads(struct file *file, char *buf, size_t size)
  634. {
  635. char *mesg = buf;
  636. int rv;
  637. if (size > 0) {
  638. int newthreads;
  639. rv = get_int(&mesg, &newthreads);
  640. if (rv)
  641. return rv;
  642. if (newthreads < 0)
  643. return -EINVAL;
  644. rv = nfsd_svc(NFS_PORT, newthreads);
  645. if (rv < 0)
  646. return rv;
  647. } else
  648. rv = nfsd_nrthreads();
  649. return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
  650. }
  651. /**
  652. * write_pool_threads - Set or report the current number of threads per pool
  653. *
  654. * Input:
  655. * buf: ignored
  656. * size: zero
  657. *
  658. * OR
  659. *
  660. * Input:
  661. * buf: C string containing whitespace-
  662. * separated unsigned integer values
  663. * representing the number of NFSD
  664. * threads to start in each pool
  665. * size: non-zero length of C string in @buf
  666. * Output:
  667. * On success: passed-in buffer filled with '\n'-terminated C
  668. * string containing integer values representing the
  669. * number of NFSD threads in each pool;
  670. * return code is the size in bytes of the string
  671. * On error: return code is zero or a negative errno value
  672. */
  673. static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
  674. {
  675. /* if size > 0, look for an array of number of threads per node
  676. * and apply them then write out number of threads per node as reply
  677. */
  678. char *mesg = buf;
  679. int i;
  680. int rv;
  681. int len;
  682. int npools;
  683. int *nthreads;
  684. mutex_lock(&nfsd_mutex);
  685. npools = nfsd_nrpools();
  686. if (npools == 0) {
  687. /*
  688. * NFS is shut down. The admin can start it by
  689. * writing to the threads file but NOT the pool_threads
  690. * file, sorry. Report zero threads.
  691. */
  692. mutex_unlock(&nfsd_mutex);
  693. strcpy(buf, "0\n");
  694. return strlen(buf);
  695. }
  696. nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
  697. rv = -ENOMEM;
  698. if (nthreads == NULL)
  699. goto out_free;
  700. if (size > 0) {
  701. for (i = 0; i < npools; i++) {
  702. rv = get_int(&mesg, &nthreads[i]);
  703. if (rv == -ENOENT)
  704. break; /* fewer numbers than pools */
  705. if (rv)
  706. goto out_free; /* syntax error */
  707. rv = -EINVAL;
  708. if (nthreads[i] < 0)
  709. goto out_free;
  710. }
  711. rv = nfsd_set_nrthreads(i, nthreads);
  712. if (rv)
  713. goto out_free;
  714. }
  715. rv = nfsd_get_nrthreads(npools, nthreads);
  716. if (rv)
  717. goto out_free;
  718. mesg = buf;
  719. size = SIMPLE_TRANSACTION_LIMIT;
  720. for (i = 0; i < npools && size > 0; i++) {
  721. snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
  722. len = strlen(mesg);
  723. size -= len;
  724. mesg += len;
  725. }
  726. rv = mesg - buf;
  727. out_free:
  728. kfree(nthreads);
  729. mutex_unlock(&nfsd_mutex);
  730. return rv;
  731. }
  732. static ssize_t __write_versions(struct file *file, char *buf, size_t size)
  733. {
  734. char *mesg = buf;
  735. char *vers, *minorp, sign;
  736. int len, num, remaining;
  737. unsigned minor;
  738. ssize_t tlen = 0;
  739. char *sep;
  740. if (size>0) {
  741. if (nfsd_serv)
  742. /* Cannot change versions without updating
  743. * nfsd_serv->sv_xdrsize, and reallocing
  744. * rq_argp and rq_resp
  745. */
  746. return -EBUSY;
  747. if (buf[size-1] != '\n')
  748. return -EINVAL;
  749. buf[size-1] = 0;
  750. vers = mesg;
  751. len = qword_get(&mesg, vers, size);
  752. if (len <= 0) return -EINVAL;
  753. do {
  754. sign = *vers;
  755. if (sign == '+' || sign == '-')
  756. num = simple_strtol((vers+1), &minorp, 0);
  757. else
  758. num = simple_strtol(vers, &minorp, 0);
  759. if (*minorp == '.') {
  760. if (num < 4)
  761. return -EINVAL;
  762. minor = simple_strtoul(minorp+1, NULL, 0);
  763. if (minor == 0)
  764. return -EINVAL;
  765. if (nfsd_minorversion(minor, sign == '-' ?
  766. NFSD_CLEAR : NFSD_SET) < 0)
  767. return -EINVAL;
  768. goto next;
  769. }
  770. switch(num) {
  771. case 2:
  772. case 3:
  773. case 4:
  774. nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
  775. break;
  776. default:
  777. return -EINVAL;
  778. }
  779. next:
  780. vers += len + 1;
  781. } while ((len = qword_get(&mesg, vers, size)) > 0);
  782. /* If all get turned off, turn them back on, as
  783. * having no versions is BAD
  784. */
  785. nfsd_reset_versions();
  786. }
  787. /* Now write current state into reply buffer */
  788. len = 0;
  789. sep = "";
  790. remaining = SIMPLE_TRANSACTION_LIMIT;
  791. for (num=2 ; num <= 4 ; num++)
  792. if (nfsd_vers(num, NFSD_AVAIL)) {
  793. len = snprintf(buf, remaining, "%s%c%d", sep,
  794. nfsd_vers(num, NFSD_TEST)?'+':'-',
  795. num);
  796. sep = " ";
  797. if (len > remaining)
  798. break;
  799. remaining -= len;
  800. buf += len;
  801. tlen += len;
  802. }
  803. if (nfsd_vers(4, NFSD_AVAIL))
  804. for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
  805. minor++) {
  806. len = snprintf(buf, remaining, " %c4.%u",
  807. (nfsd_vers(4, NFSD_TEST) &&
  808. nfsd_minorversion(minor, NFSD_TEST)) ?
  809. '+' : '-',
  810. minor);
  811. if (len > remaining)
  812. break;
  813. remaining -= len;
  814. buf += len;
  815. tlen += len;
  816. }
  817. len = snprintf(buf, remaining, "\n");
  818. if (len > remaining)
  819. return -EINVAL;
  820. return tlen + len;
  821. }
  822. /**
  823. * write_versions - Set or report the available NFS protocol versions
  824. *
  825. * Input:
  826. * buf: ignored
  827. * size: zero
  828. * Output:
  829. * On success: passed-in buffer filled with '\n'-terminated C
  830. * string containing positive or negative integer
  831. * values representing the current status of each
  832. * protocol version;
  833. * return code is the size in bytes of the string
  834. * On error: return code is zero or a negative errno value
  835. *
  836. * OR
  837. *
  838. * Input:
  839. * buf: C string containing whitespace-
  840. * separated positive or negative
  841. * integer values representing NFS
  842. * protocol versions to enable ("+n")
  843. * or disable ("-n")
  844. * size: non-zero length of C string in @buf
  845. * Output:
  846. * On success: status of zero or more protocol versions has
  847. * been updated; passed-in buffer filled with
  848. * '\n'-terminated C string containing positive
  849. * or negative integer values representing the
  850. * current status of each protocol version;
  851. * return code is the size in bytes of the string
  852. * On error: return code is zero or a negative errno value
  853. */
  854. static ssize_t write_versions(struct file *file, char *buf, size_t size)
  855. {
  856. ssize_t rv;
  857. mutex_lock(&nfsd_mutex);
  858. rv = __write_versions(file, buf, size);
  859. mutex_unlock(&nfsd_mutex);
  860. return rv;
  861. }
  862. /*
  863. * Zero-length write. Return a list of NFSD's current listener
  864. * transports.
  865. */
  866. static ssize_t __write_ports_names(char *buf)
  867. {
  868. if (nfsd_serv == NULL)
  869. return 0;
  870. return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
  871. }
  872. /*
  873. * A single 'fd' number was written, in which case it must be for
  874. * a socket of a supported family/protocol, and we use it as an
  875. * nfsd listener.
  876. */
  877. static ssize_t __write_ports_addfd(char *buf)
  878. {
  879. char *mesg = buf;
  880. int fd, err;
  881. err = get_int(&mesg, &fd);
  882. if (err != 0 || fd < 0)
  883. return -EINVAL;
  884. err = nfsd_create_serv();
  885. if (err != 0)
  886. return err;
  887. err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
  888. if (err < 0) {
  889. svc_destroy(nfsd_serv);
  890. return err;
  891. }
  892. /* Decrease the count, but don't shut down the service */
  893. nfsd_serv->sv_nrthreads--;
  894. return err;
  895. }
  896. /*
  897. * A '-' followed by the 'name' of a socket means we close the socket.
  898. */
  899. static ssize_t __write_ports_delfd(char *buf)
  900. {
  901. char *toclose;
  902. int len = 0;
  903. toclose = kstrdup(buf + 1, GFP_KERNEL);
  904. if (toclose == NULL)
  905. return -ENOMEM;
  906. if (nfsd_serv != NULL)
  907. len = svc_sock_names(nfsd_serv, buf,
  908. SIMPLE_TRANSACTION_LIMIT, toclose);
  909. kfree(toclose);
  910. return len;
  911. }
  912. /*
  913. * A transport listener is added by writing it's transport name and
  914. * a port number.
  915. */
  916. static ssize_t __write_ports_addxprt(char *buf)
  917. {
  918. char transport[16];
  919. struct svc_xprt *xprt;
  920. int port, err;
  921. if (sscanf(buf, "%15s %4u", transport, &port) != 2)
  922. return -EINVAL;
  923. if (port < 1 || port > USHRT_MAX)
  924. return -EINVAL;
  925. err = nfsd_create_serv();
  926. if (err != 0)
  927. return err;
  928. err = svc_create_xprt(nfsd_serv, transport, &init_net,
  929. PF_INET, port, SVC_SOCK_ANONYMOUS);
  930. if (err < 0)
  931. goto out_err;
  932. err = svc_create_xprt(nfsd_serv, transport, &init_net,
  933. PF_INET6, port, SVC_SOCK_ANONYMOUS);
  934. if (err < 0 && err != -EAFNOSUPPORT)
  935. goto out_close;
  936. /* Decrease the count, but don't shut down the service */
  937. nfsd_serv->sv_nrthreads--;
  938. return 0;
  939. out_close:
  940. xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port);
  941. if (xprt != NULL) {
  942. svc_close_xprt(xprt);
  943. svc_xprt_put(xprt);
  944. }
  945. out_err:
  946. svc_destroy(nfsd_serv);
  947. return err;
  948. }
  949. /*
  950. * A transport listener is removed by writing a "-", it's transport
  951. * name, and it's port number.
  952. */
  953. static ssize_t __write_ports_delxprt(char *buf)
  954. {
  955. struct svc_xprt *xprt;
  956. char transport[16];
  957. int port;
  958. if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
  959. return -EINVAL;
  960. if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
  961. return -EINVAL;
  962. xprt = svc_find_xprt(nfsd_serv, transport, AF_UNSPEC, port);
  963. if (xprt == NULL)
  964. return -ENOTCONN;
  965. svc_close_xprt(xprt);
  966. svc_xprt_put(xprt);
  967. return 0;
  968. }
  969. static ssize_t __write_ports(struct file *file, char *buf, size_t size)
  970. {
  971. if (size == 0)
  972. return __write_ports_names(buf);
  973. if (isdigit(buf[0]))
  974. return __write_ports_addfd(buf);
  975. if (buf[0] == '-' && isdigit(buf[1]))
  976. return __write_ports_delfd(buf);
  977. if (isalpha(buf[0]))
  978. return __write_ports_addxprt(buf);
  979. if (buf[0] == '-' && isalpha(buf[1]))
  980. return __write_ports_delxprt(buf);
  981. return -EINVAL;
  982. }
  983. /**
  984. * write_ports - Pass a socket file descriptor or transport name to listen on
  985. *
  986. * Input:
  987. * buf: ignored
  988. * size: zero
  989. * Output:
  990. * On success: passed-in buffer filled with a '\n'-terminated C
  991. * string containing a whitespace-separated list of
  992. * named NFSD listeners;
  993. * return code is the size in bytes of the string
  994. * On error: return code is zero or a negative errno value
  995. *
  996. * OR
  997. *
  998. * Input:
  999. * buf: C string containing an unsigned
  1000. * integer value representing a bound
  1001. * but unconnected socket that is to be
  1002. * used as an NFSD listener; listen(3)
  1003. * must be called for a SOCK_STREAM
  1004. * socket, otherwise it is ignored
  1005. * size: non-zero length of C string in @buf
  1006. * Output:
  1007. * On success: NFS service is started;
  1008. * passed-in buffer filled with a '\n'-terminated C
  1009. * string containing a unique alphanumeric name of
  1010. * the listener;
  1011. * return code is the size in bytes of the string
  1012. * On error: return code is a negative errno value
  1013. *
  1014. * OR
  1015. *
  1016. * Input:
  1017. * buf: C string containing a "-" followed
  1018. * by an integer value representing a
  1019. * previously passed in socket file
  1020. * descriptor
  1021. * size: non-zero length of C string in @buf
  1022. * Output:
  1023. * On success: NFS service no longer listens on that socket;
  1024. * passed-in buffer filled with a '\n'-terminated C
  1025. * string containing a unique name of the listener;
  1026. * return code is the size in bytes of the string
  1027. * On error: return code is a negative errno value
  1028. *
  1029. * OR
  1030. *
  1031. * Input:
  1032. * buf: C string containing a transport
  1033. * name and an unsigned integer value
  1034. * representing the port to listen on,
  1035. * separated by whitespace
  1036. * size: non-zero length of C string in @buf
  1037. * Output:
  1038. * On success: returns zero; NFS service is started
  1039. * On error: return code is a negative errno value
  1040. *
  1041. * OR
  1042. *
  1043. * Input:
  1044. * buf: C string containing a "-" followed
  1045. * by a transport name and an unsigned
  1046. * integer value representing the port
  1047. * to listen on, separated by whitespace
  1048. * size: non-zero length of C string in @buf
  1049. * Output:
  1050. * On success: returns zero; NFS service no longer listens
  1051. * on that transport
  1052. * On error: return code is a negative errno value
  1053. */
  1054. static ssize_t write_ports(struct file *file, char *buf, size_t size)
  1055. {
  1056. ssize_t rv;
  1057. mutex_lock(&nfsd_mutex);
  1058. rv = __write_ports(file, buf, size);
  1059. mutex_unlock(&nfsd_mutex);
  1060. return rv;
  1061. }
  1062. int nfsd_max_blksize;
  1063. /**
  1064. * write_maxblksize - Set or report the current NFS blksize
  1065. *
  1066. * Input:
  1067. * buf: ignored
  1068. * size: zero
  1069. *
  1070. * OR
  1071. *
  1072. * Input:
  1073. * buf: C string containing an unsigned
  1074. * integer value representing the new
  1075. * NFS blksize
  1076. * size: non-zero length of C string in @buf
  1077. * Output:
  1078. * On success: passed-in buffer filled with '\n'-terminated C string
  1079. * containing numeric value of the current NFS blksize
  1080. * setting;
  1081. * return code is the size in bytes of the string
  1082. * On error: return code is zero or a negative errno value
  1083. */
  1084. static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
  1085. {
  1086. char *mesg = buf;
  1087. if (size > 0) {
  1088. int bsize;
  1089. int rv = get_int(&mesg, &bsize);
  1090. if (rv)
  1091. return rv;
  1092. /* force bsize into allowed range and
  1093. * required alignment.
  1094. */
  1095. if (bsize < 1024)
  1096. bsize = 1024;
  1097. if (bsize > NFSSVC_MAXBLKSIZE)
  1098. bsize = NFSSVC_MAXBLKSIZE;
  1099. bsize &= ~(1024-1);
  1100. mutex_lock(&nfsd_mutex);
  1101. if (nfsd_serv) {
  1102. mutex_unlock(&nfsd_mutex);
  1103. return -EBUSY;
  1104. }
  1105. nfsd_max_blksize = bsize;
  1106. mutex_unlock(&nfsd_mutex);
  1107. }
  1108. return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
  1109. nfsd_max_blksize);
  1110. }
  1111. #ifdef CONFIG_NFSD_V4
  1112. static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
  1113. {
  1114. char *mesg = buf;
  1115. int rv, i;
  1116. if (size > 0) {
  1117. if (nfsd_serv)
  1118. return -EBUSY;
  1119. rv = get_int(&mesg, &i);
  1120. if (rv)
  1121. return rv;
  1122. /*
  1123. * Some sanity checking. We don't have a reason for
  1124. * these particular numbers, but problems with the
  1125. * extremes are:
  1126. * - Too short: the briefest network outage may
  1127. * cause clients to lose all their locks. Also,
  1128. * the frequent polling may be wasteful.
  1129. * - Too long: do you really want reboot recovery
  1130. * to take more than an hour? Or to make other
  1131. * clients wait an hour before being able to
  1132. * revoke a dead client's locks?
  1133. */
  1134. if (i < 10 || i > 3600)
  1135. return -EINVAL;
  1136. *time = i;
  1137. }
  1138. return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
  1139. }
  1140. static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
  1141. {
  1142. ssize_t rv;
  1143. mutex_lock(&nfsd_mutex);
  1144. rv = __nfsd4_write_time(file, buf, size, time);
  1145. mutex_unlock(&nfsd_mutex);
  1146. return rv;
  1147. }
  1148. /**
  1149. * write_leasetime - Set or report the current NFSv4 lease time
  1150. *
  1151. * Input:
  1152. * buf: ignored
  1153. * size: zero
  1154. *
  1155. * OR
  1156. *
  1157. * Input:
  1158. * buf: C string containing an unsigned
  1159. * integer value representing the new
  1160. * NFSv4 lease expiry time
  1161. * size: non-zero length of C string in @buf
  1162. * Output:
  1163. * On success: passed-in buffer filled with '\n'-terminated C
  1164. * string containing unsigned integer value of the
  1165. * current lease expiry time;
  1166. * return code is the size in bytes of the string
  1167. * On error: return code is zero or a negative errno value
  1168. */
  1169. static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  1170. {
  1171. return nfsd4_write_time(file, buf, size, &nfsd4_lease);
  1172. }
  1173. /**
  1174. * write_gracetime - Set or report current NFSv4 grace period time
  1175. *
  1176. * As above, but sets the time of the NFSv4 grace period.
  1177. *
  1178. * Note this should never be set to less than the *previous*
  1179. * lease-period time, but we don't try to enforce this. (In the common
  1180. * case (a new boot), we don't know what the previous lease time was
  1181. * anyway.)
  1182. */
  1183. static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
  1184. {
  1185. return nfsd4_write_time(file, buf, size, &nfsd4_grace);
  1186. }
  1187. extern char *nfs4_recoverydir(void);
  1188. static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
  1189. {
  1190. char *mesg = buf;
  1191. char *recdir;
  1192. int len, status;
  1193. if (size > 0) {
  1194. if (nfsd_serv)
  1195. return -EBUSY;
  1196. if (size > PATH_MAX || buf[size-1] != '\n')
  1197. return -EINVAL;
  1198. buf[size-1] = 0;
  1199. recdir = mesg;
  1200. len = qword_get(&mesg, recdir, size);
  1201. if (len <= 0)
  1202. return -EINVAL;
  1203. status = nfs4_reset_recoverydir(recdir);
  1204. if (status)
  1205. return status;
  1206. }
  1207. return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
  1208. nfs4_recoverydir());
  1209. }
  1210. /**
  1211. * write_recoverydir - Set or report the pathname of the recovery directory
  1212. *
  1213. * Input:
  1214. * buf: ignored
  1215. * size: zero
  1216. *
  1217. * OR
  1218. *
  1219. * Input:
  1220. * buf: C string containing the pathname
  1221. * of the directory on a local file
  1222. * system containing permanent NFSv4
  1223. * recovery data
  1224. * size: non-zero length of C string in @buf
  1225. * Output:
  1226. * On success: passed-in buffer filled with '\n'-terminated C string
  1227. * containing the current recovery pathname setting;
  1228. * return code is the size in bytes of the string
  1229. * On error: return code is zero or a negative errno value
  1230. */
  1231. static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
  1232. {
  1233. ssize_t rv;
  1234. mutex_lock(&nfsd_mutex);
  1235. rv = __write_recoverydir(file, buf, size);
  1236. mutex_unlock(&nfsd_mutex);
  1237. return rv;
  1238. }
  1239. #endif
  1240. /*----------------------------------------------------------------------------*/
  1241. /*
  1242. * populating the filesystem.
  1243. */
  1244. static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
  1245. {
  1246. static struct tree_descr nfsd_files[] = {
  1247. #ifdef CONFIG_NFSD_DEPRECATED
  1248. [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
  1249. [NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
  1250. [NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
  1251. [NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
  1252. [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
  1253. [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
  1254. [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
  1255. #endif
  1256. [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
  1257. [NFSD_Export_features] = {"export_features",
  1258. &export_features_operations, S_IRUGO},
  1259. [NFSD_FO_UnlockIP] = {"unlock_ip",
  1260. &transaction_ops, S_IWUSR|S_IRUSR},
  1261. [NFSD_FO_UnlockFS] = {"unlock_filesystem",
  1262. &transaction_ops, S_IWUSR|S_IRUSR},
  1263. [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
  1264. [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
  1265. [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
  1266. [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
  1267. [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
  1268. [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
  1269. [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
  1270. #ifdef CONFIG_NFSD_V4
  1271. [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
  1272. [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
  1273. [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
  1274. #endif
  1275. /* last one */ {""}
  1276. };
  1277. return simple_fill_super(sb, 0x6e667364, nfsd_files);
  1278. }
  1279. static struct dentry *nfsd_mount(struct file_system_type *fs_type,
  1280. int flags, const char *dev_name, void *data)
  1281. {
  1282. return mount_single(fs_type, flags, data, nfsd_fill_super);
  1283. }
  1284. static struct file_system_type nfsd_fs_type = {
  1285. .owner = THIS_MODULE,
  1286. .name = "nfsd",
  1287. .mount = nfsd_mount,
  1288. .kill_sb = kill_litter_super,
  1289. };
  1290. #ifdef CONFIG_PROC_FS
  1291. static int create_proc_exports_entry(void)
  1292. {
  1293. struct proc_dir_entry *entry;
  1294. entry = proc_mkdir("fs/nfs", NULL);
  1295. if (!entry)
  1296. return -ENOMEM;
  1297. entry = proc_create("exports", 0, entry, &exports_operations);
  1298. if (!entry)
  1299. return -ENOMEM;
  1300. return 0;
  1301. }
  1302. #else /* CONFIG_PROC_FS */
  1303. static int create_proc_exports_entry(void)
  1304. {
  1305. return 0;
  1306. }
  1307. #endif
  1308. static int __init init_nfsd(void)
  1309. {
  1310. int retval;
  1311. printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
  1312. retval = nfs4_state_init(); /* nfs4 locking state */
  1313. if (retval)
  1314. return retval;
  1315. nfsd_stat_init(); /* Statistics */
  1316. retval = nfsd_reply_cache_init();
  1317. if (retval)
  1318. goto out_free_stat;
  1319. retval = nfsd_export_init();
  1320. if (retval)
  1321. goto out_free_cache;
  1322. nfsd_lockd_init(); /* lockd->nfsd callbacks */
  1323. retval = nfsd_idmap_init();
  1324. if (retval)
  1325. goto out_free_lockd;
  1326. retval = create_proc_exports_entry();
  1327. if (retval)
  1328. goto out_free_idmap;
  1329. retval = register_filesystem(&nfsd_fs_type);
  1330. if (retval)
  1331. goto out_free_all;
  1332. return 0;
  1333. out_free_all:
  1334. remove_proc_entry("fs/nfs/exports", NULL);
  1335. remove_proc_entry("fs/nfs", NULL);
  1336. out_free_idmap:
  1337. nfsd_idmap_shutdown();
  1338. out_free_lockd:
  1339. nfsd_lockd_shutdown();
  1340. nfsd_export_shutdown();
  1341. out_free_cache:
  1342. nfsd_reply_cache_shutdown();
  1343. out_free_stat:
  1344. nfsd_stat_shutdown();
  1345. nfsd4_free_slabs();
  1346. return retval;
  1347. }
  1348. static void __exit exit_nfsd(void)
  1349. {
  1350. nfsd_export_shutdown();
  1351. nfsd_reply_cache_shutdown();
  1352. remove_proc_entry("fs/nfs/exports", NULL);
  1353. remove_proc_entry("fs/nfs", NULL);
  1354. nfsd_stat_shutdown();
  1355. nfsd_lockd_shutdown();
  1356. nfsd_idmap_shutdown();
  1357. nfsd4_free_slabs();
  1358. unregister_filesystem(&nfsd_fs_type);
  1359. }
  1360. MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
  1361. MODULE_LICENSE("GPL");
  1362. module_init(init_nfsd)
  1363. module_exit(exit_nfsd)