nfs4recover.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298
  1. /*
  2. * Copyright (c) 2004 The Regents of the University of Michigan.
  3. * Copyright (c) 2012 Jeff Layton <jlayton@redhat.com>
  4. * All rights reserved.
  5. *
  6. * Andy Adamson <andros@citi.umich.edu>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  22. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  23. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  24. * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  26. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  27. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  28. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. */
  34. #include <linux/file.h>
  35. #include <linux/slab.h>
  36. #include <linux/namei.h>
  37. #include <linux/crypto.h>
  38. #include <linux/sched.h>
  39. #include <linux/fs.h>
  40. #include <linux/module.h>
  41. #include <net/net_namespace.h>
  42. #include <linux/sunrpc/rpc_pipe_fs.h>
  43. #include <linux/sunrpc/clnt.h>
  44. #include <linux/nfsd/cld.h>
  45. #include "nfsd.h"
  46. #include "state.h"
  47. #include "vfs.h"
  48. #include "netns.h"
  49. #define NFSDDBG_FACILITY NFSDDBG_PROC
  50. /* Declarations */
  51. struct nfsd4_client_tracking_ops {
  52. int (*init)(struct net *);
  53. void (*exit)(struct net *);
  54. void (*create)(struct nfs4_client *);
  55. void (*remove)(struct nfs4_client *);
  56. int (*check)(struct nfs4_client *);
  57. void (*grace_done)(struct net *, time_t);
  58. };
  59. /* Globals */
  60. static struct file *rec_file;
  61. static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
  62. static struct nfsd4_client_tracking_ops *client_tracking_ops;
  63. static bool in_grace;
  64. static int
  65. nfs4_save_creds(const struct cred **original_creds)
  66. {
  67. struct cred *new;
  68. new = prepare_creds();
  69. if (!new)
  70. return -ENOMEM;
  71. new->fsuid = 0;
  72. new->fsgid = 0;
  73. *original_creds = override_creds(new);
  74. put_cred(new);
  75. return 0;
  76. }
  77. static void
  78. nfs4_reset_creds(const struct cred *original)
  79. {
  80. revert_creds(original);
  81. }
  82. static void
  83. md5_to_hex(char *out, char *md5)
  84. {
  85. int i;
  86. for (i=0; i<16; i++) {
  87. unsigned char c = md5[i];
  88. *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
  89. *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
  90. }
  91. *out = '\0';
  92. }
  93. __be32
  94. nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
  95. {
  96. struct xdr_netobj cksum;
  97. struct hash_desc desc;
  98. struct scatterlist sg;
  99. __be32 status = nfserr_jukebox;
  100. dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
  101. clname->len, clname->data);
  102. desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
  103. desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
  104. if (IS_ERR(desc.tfm))
  105. goto out_no_tfm;
  106. cksum.len = crypto_hash_digestsize(desc.tfm);
  107. cksum.data = kmalloc(cksum.len, GFP_KERNEL);
  108. if (cksum.data == NULL)
  109. goto out;
  110. sg_init_one(&sg, clname->data, clname->len);
  111. if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data))
  112. goto out;
  113. md5_to_hex(dname, cksum.data);
  114. status = nfs_ok;
  115. out:
  116. kfree(cksum.data);
  117. crypto_free_hash(desc.tfm);
  118. out_no_tfm:
  119. return status;
  120. }
  121. static void
  122. nfsd4_create_clid_dir(struct nfs4_client *clp)
  123. {
  124. const struct cred *original_cred;
  125. char *dname = clp->cl_recdir;
  126. struct dentry *dir, *dentry;
  127. struct nfs4_client_reclaim *crp;
  128. int status;
  129. dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
  130. if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
  131. return;
  132. if (!rec_file)
  133. return;
  134. status = nfs4_save_creds(&original_cred);
  135. if (status < 0)
  136. return;
  137. status = mnt_want_write_file(rec_file);
  138. if (status)
  139. return;
  140. dir = rec_file->f_path.dentry;
  141. /* lock the parent */
  142. mutex_lock(&dir->d_inode->i_mutex);
  143. dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1);
  144. if (IS_ERR(dentry)) {
  145. status = PTR_ERR(dentry);
  146. goto out_unlock;
  147. }
  148. if (dentry->d_inode)
  149. /*
  150. * In the 4.1 case, where we're called from
  151. * reclaim_complete(), records from the previous reboot
  152. * may still be left, so this is OK.
  153. *
  154. * In the 4.0 case, we should never get here; but we may
  155. * as well be forgiving and just succeed silently.
  156. */
  157. goto out_put;
  158. status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU);
  159. out_put:
  160. dput(dentry);
  161. out_unlock:
  162. mutex_unlock(&dir->d_inode->i_mutex);
  163. if (status == 0) {
  164. if (in_grace) {
  165. crp = nfs4_client_to_reclaim(clp->cl_recdir);
  166. if (crp)
  167. crp->cr_clp = clp;
  168. }
  169. vfs_fsync(rec_file, 0);
  170. } else {
  171. printk(KERN_ERR "NFSD: failed to write recovery record"
  172. " (err %d); please check that %s exists"
  173. " and is writeable", status,
  174. user_recovery_dirname);
  175. }
  176. mnt_drop_write_file(rec_file);
  177. nfs4_reset_creds(original_cred);
  178. }
  179. typedef int (recdir_func)(struct dentry *, struct dentry *);
  180. struct name_list {
  181. char name[HEXDIR_LEN];
  182. struct list_head list;
  183. };
  184. static int
  185. nfsd4_build_namelist(void *arg, const char *name, int namlen,
  186. loff_t offset, u64 ino, unsigned int d_type)
  187. {
  188. struct list_head *names = arg;
  189. struct name_list *entry;
  190. if (namlen != HEXDIR_LEN - 1)
  191. return 0;
  192. entry = kmalloc(sizeof(struct name_list), GFP_KERNEL);
  193. if (entry == NULL)
  194. return -ENOMEM;
  195. memcpy(entry->name, name, HEXDIR_LEN - 1);
  196. entry->name[HEXDIR_LEN - 1] = '\0';
  197. list_add(&entry->list, names);
  198. return 0;
  199. }
  200. static int
  201. nfsd4_list_rec_dir(recdir_func *f)
  202. {
  203. const struct cred *original_cred;
  204. struct dentry *dir = rec_file->f_path.dentry;
  205. LIST_HEAD(names);
  206. int status;
  207. status = nfs4_save_creds(&original_cred);
  208. if (status < 0)
  209. return status;
  210. status = vfs_llseek(rec_file, 0, SEEK_SET);
  211. if (status < 0) {
  212. nfs4_reset_creds(original_cred);
  213. return status;
  214. }
  215. status = vfs_readdir(rec_file, nfsd4_build_namelist, &names);
  216. mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
  217. while (!list_empty(&names)) {
  218. struct name_list *entry;
  219. entry = list_entry(names.next, struct name_list, list);
  220. if (!status) {
  221. struct dentry *dentry;
  222. dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
  223. if (IS_ERR(dentry)) {
  224. status = PTR_ERR(dentry);
  225. break;
  226. }
  227. status = f(dir, dentry);
  228. dput(dentry);
  229. }
  230. list_del(&entry->list);
  231. kfree(entry);
  232. }
  233. mutex_unlock(&dir->d_inode->i_mutex);
  234. nfs4_reset_creds(original_cred);
  235. return status;
  236. }
  237. static int
  238. nfsd4_unlink_clid_dir(char *name, int namlen)
  239. {
  240. struct dentry *dir, *dentry;
  241. int status;
  242. dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
  243. dir = rec_file->f_path.dentry;
  244. mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
  245. dentry = lookup_one_len(name, dir, namlen);
  246. if (IS_ERR(dentry)) {
  247. status = PTR_ERR(dentry);
  248. goto out_unlock;
  249. }
  250. status = -ENOENT;
  251. if (!dentry->d_inode)
  252. goto out;
  253. status = vfs_rmdir(dir->d_inode, dentry);
  254. out:
  255. dput(dentry);
  256. out_unlock:
  257. mutex_unlock(&dir->d_inode->i_mutex);
  258. return status;
  259. }
  260. static void
  261. nfsd4_remove_clid_dir(struct nfs4_client *clp)
  262. {
  263. const struct cred *original_cred;
  264. struct nfs4_client_reclaim *crp;
  265. int status;
  266. if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
  267. return;
  268. status = mnt_want_write_file(rec_file);
  269. if (status)
  270. goto out;
  271. clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
  272. status = nfs4_save_creds(&original_cred);
  273. if (status < 0)
  274. goto out_drop_write;
  275. status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
  276. nfs4_reset_creds(original_cred);
  277. if (status == 0) {
  278. vfs_fsync(rec_file, 0);
  279. if (in_grace) {
  280. /* remove reclaim record */
  281. crp = nfsd4_find_reclaim_client(clp->cl_recdir);
  282. if (crp)
  283. nfs4_remove_reclaim_record(crp);
  284. }
  285. }
  286. out_drop_write:
  287. mnt_drop_write_file(rec_file);
  288. out:
  289. if (status)
  290. printk("NFSD: Failed to remove expired client state directory"
  291. " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
  292. }
  293. static int
  294. purge_old(struct dentry *parent, struct dentry *child)
  295. {
  296. int status;
  297. if (nfs4_has_reclaimed_state(child->d_name.name))
  298. return 0;
  299. status = vfs_rmdir(parent->d_inode, child);
  300. if (status)
  301. printk("failed to remove client recovery directory %s\n",
  302. child->d_name.name);
  303. /* Keep trying, success or failure: */
  304. return 0;
  305. }
  306. static void
  307. nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
  308. {
  309. int status;
  310. in_grace = false;
  311. if (!rec_file)
  312. return;
  313. status = mnt_want_write_file(rec_file);
  314. if (status)
  315. goto out;
  316. status = nfsd4_list_rec_dir(purge_old);
  317. if (status == 0)
  318. vfs_fsync(rec_file, 0);
  319. mnt_drop_write_file(rec_file);
  320. out:
  321. if (status)
  322. printk("nfsd4: failed to purge old clients from recovery"
  323. " directory %s\n", rec_file->f_path.dentry->d_name.name);
  324. }
  325. static int
  326. load_recdir(struct dentry *parent, struct dentry *child)
  327. {
  328. if (child->d_name.len != HEXDIR_LEN - 1) {
  329. printk("nfsd4: illegal name %s in recovery directory\n",
  330. child->d_name.name);
  331. /* Keep trying; maybe the others are OK: */
  332. return 0;
  333. }
  334. nfs4_client_to_reclaim(child->d_name.name);
  335. return 0;
  336. }
  337. static int
  338. nfsd4_recdir_load(void) {
  339. int status;
  340. if (!rec_file)
  341. return 0;
  342. status = nfsd4_list_rec_dir(load_recdir);
  343. if (status)
  344. printk("nfsd4: failed loading clients from recovery"
  345. " directory %s\n", rec_file->f_path.dentry->d_name.name);
  346. return status;
  347. }
  348. /*
  349. * Hold reference to the recovery directory.
  350. */
  351. static int
  352. nfsd4_init_recdir(void)
  353. {
  354. const struct cred *original_cred;
  355. int status;
  356. printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
  357. user_recovery_dirname);
  358. BUG_ON(rec_file);
  359. status = nfs4_save_creds(&original_cred);
  360. if (status < 0) {
  361. printk("NFSD: Unable to change credentials to find recovery"
  362. " directory: error %d\n",
  363. status);
  364. return status;
  365. }
  366. rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
  367. if (IS_ERR(rec_file)) {
  368. printk("NFSD: unable to find recovery directory %s\n",
  369. user_recovery_dirname);
  370. status = PTR_ERR(rec_file);
  371. rec_file = NULL;
  372. }
  373. nfs4_reset_creds(original_cred);
  374. if (!status)
  375. in_grace = true;
  376. return status;
  377. }
  378. static int
  379. nfsd4_load_reboot_recovery_data(struct net *net)
  380. {
  381. int status;
  382. /* XXX: The legacy code won't work in a container */
  383. if (net != &init_net) {
  384. WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client "
  385. "tracking in a container!\n");
  386. return -EINVAL;
  387. }
  388. nfs4_lock_state();
  389. status = nfsd4_init_recdir();
  390. if (!status)
  391. status = nfsd4_recdir_load();
  392. nfs4_unlock_state();
  393. if (status)
  394. printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
  395. return status;
  396. }
  397. static void
  398. nfsd4_shutdown_recdir(void)
  399. {
  400. if (!rec_file)
  401. return;
  402. fput(rec_file);
  403. rec_file = NULL;
  404. }
  405. static void
  406. nfsd4_legacy_tracking_exit(struct net *net)
  407. {
  408. nfs4_release_reclaim();
  409. nfsd4_shutdown_recdir();
  410. }
  411. /*
  412. * Change the NFSv4 recovery directory to recdir.
  413. */
  414. int
  415. nfs4_reset_recoverydir(char *recdir)
  416. {
  417. int status;
  418. struct path path;
  419. status = kern_path(recdir, LOOKUP_FOLLOW, &path);
  420. if (status)
  421. return status;
  422. status = -ENOTDIR;
  423. if (S_ISDIR(path.dentry->d_inode->i_mode)) {
  424. strcpy(user_recovery_dirname, recdir);
  425. status = 0;
  426. }
  427. path_put(&path);
  428. return status;
  429. }
  430. char *
  431. nfs4_recoverydir(void)
  432. {
  433. return user_recovery_dirname;
  434. }
  435. static int
  436. nfsd4_check_legacy_client(struct nfs4_client *clp)
  437. {
  438. struct nfs4_client_reclaim *crp;
  439. /* did we already find that this client is stable? */
  440. if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
  441. return 0;
  442. /* look for it in the reclaim hashtable otherwise */
  443. crp = nfsd4_find_reclaim_client(clp->cl_recdir);
  444. if (crp) {
  445. set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
  446. crp->cr_clp = clp;
  447. return 0;
  448. }
  449. return -ENOENT;
  450. }
  451. static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
  452. .init = nfsd4_load_reboot_recovery_data,
  453. .exit = nfsd4_legacy_tracking_exit,
  454. .create = nfsd4_create_clid_dir,
  455. .remove = nfsd4_remove_clid_dir,
  456. .check = nfsd4_check_legacy_client,
  457. .grace_done = nfsd4_recdir_purge_old,
  458. };
  459. /* Globals */
  460. #define NFSD_PIPE_DIR "nfsd"
  461. #define NFSD_CLD_PIPE "cld"
  462. /* per-net-ns structure for holding cld upcall info */
  463. struct cld_net {
  464. struct rpc_pipe *cn_pipe;
  465. spinlock_t cn_lock;
  466. struct list_head cn_list;
  467. unsigned int cn_xid;
  468. };
  469. struct cld_upcall {
  470. struct list_head cu_list;
  471. struct cld_net *cu_net;
  472. struct task_struct *cu_task;
  473. struct cld_msg cu_msg;
  474. };
  475. static int
  476. __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
  477. {
  478. int ret;
  479. struct rpc_pipe_msg msg;
  480. memset(&msg, 0, sizeof(msg));
  481. msg.data = cmsg;
  482. msg.len = sizeof(*cmsg);
  483. /*
  484. * Set task state before we queue the upcall. That prevents
  485. * wake_up_process in the downcall from racing with schedule.
  486. */
  487. set_current_state(TASK_UNINTERRUPTIBLE);
  488. ret = rpc_queue_upcall(pipe, &msg);
  489. if (ret < 0) {
  490. set_current_state(TASK_RUNNING);
  491. goto out;
  492. }
  493. schedule();
  494. set_current_state(TASK_RUNNING);
  495. if (msg.errno < 0)
  496. ret = msg.errno;
  497. out:
  498. return ret;
  499. }
  500. static int
  501. cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
  502. {
  503. int ret;
  504. /*
  505. * -EAGAIN occurs when pipe is closed and reopened while there are
  506. * upcalls queued.
  507. */
  508. do {
  509. ret = __cld_pipe_upcall(pipe, cmsg);
  510. } while (ret == -EAGAIN);
  511. return ret;
  512. }
  513. static ssize_t
  514. cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
  515. {
  516. struct cld_upcall *tmp, *cup;
  517. struct cld_msg __user *cmsg = (struct cld_msg __user *)src;
  518. uint32_t xid;
  519. struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info,
  520. nfsd_net_id);
  521. struct cld_net *cn = nn->cld_net;
  522. if (mlen != sizeof(*cmsg)) {
  523. dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
  524. sizeof(*cmsg));
  525. return -EINVAL;
  526. }
  527. /* copy just the xid so we can try to find that */
  528. if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) {
  529. dprintk("%s: error when copying xid from userspace", __func__);
  530. return -EFAULT;
  531. }
  532. /* walk the list and find corresponding xid */
  533. cup = NULL;
  534. spin_lock(&cn->cn_lock);
  535. list_for_each_entry(tmp, &cn->cn_list, cu_list) {
  536. if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) {
  537. cup = tmp;
  538. list_del_init(&cup->cu_list);
  539. break;
  540. }
  541. }
  542. spin_unlock(&cn->cn_lock);
  543. /* couldn't find upcall? */
  544. if (!cup) {
  545. dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid);
  546. return -EINVAL;
  547. }
  548. if (copy_from_user(&cup->cu_msg, src, mlen) != 0)
  549. return -EFAULT;
  550. wake_up_process(cup->cu_task);
  551. return mlen;
  552. }
  553. static void
  554. cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
  555. {
  556. struct cld_msg *cmsg = msg->data;
  557. struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
  558. cu_msg);
  559. /* errno >= 0 means we got a downcall */
  560. if (msg->errno >= 0)
  561. return;
  562. wake_up_process(cup->cu_task);
  563. }
  564. static const struct rpc_pipe_ops cld_upcall_ops = {
  565. .upcall = rpc_pipe_generic_upcall,
  566. .downcall = cld_pipe_downcall,
  567. .destroy_msg = cld_pipe_destroy_msg,
  568. };
  569. static struct dentry *
  570. nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
  571. {
  572. struct dentry *dir, *dentry;
  573. dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
  574. if (dir == NULL)
  575. return ERR_PTR(-ENOENT);
  576. dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
  577. dput(dir);
  578. return dentry;
  579. }
  580. static void
  581. nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
  582. {
  583. if (pipe->dentry)
  584. rpc_unlink(pipe->dentry);
  585. }
  586. static struct dentry *
  587. nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
  588. {
  589. struct super_block *sb;
  590. struct dentry *dentry;
  591. sb = rpc_get_sb_net(net);
  592. if (!sb)
  593. return NULL;
  594. dentry = nfsd4_cld_register_sb(sb, pipe);
  595. rpc_put_sb_net(net);
  596. return dentry;
  597. }
  598. static void
  599. nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
  600. {
  601. struct super_block *sb;
  602. sb = rpc_get_sb_net(net);
  603. if (sb) {
  604. nfsd4_cld_unregister_sb(pipe);
  605. rpc_put_sb_net(net);
  606. }
  607. }
  608. /* Initialize rpc_pipefs pipe for communication with client tracking daemon */
  609. static int
  610. nfsd4_init_cld_pipe(struct net *net)
  611. {
  612. int ret;
  613. struct dentry *dentry;
  614. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  615. struct cld_net *cn;
  616. if (nn->cld_net)
  617. return 0;
  618. cn = kzalloc(sizeof(*cn), GFP_KERNEL);
  619. if (!cn) {
  620. ret = -ENOMEM;
  621. goto err;
  622. }
  623. cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
  624. if (IS_ERR(cn->cn_pipe)) {
  625. ret = PTR_ERR(cn->cn_pipe);
  626. goto err;
  627. }
  628. spin_lock_init(&cn->cn_lock);
  629. INIT_LIST_HEAD(&cn->cn_list);
  630. dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
  631. if (IS_ERR(dentry)) {
  632. ret = PTR_ERR(dentry);
  633. goto err_destroy_data;
  634. }
  635. cn->cn_pipe->dentry = dentry;
  636. nn->cld_net = cn;
  637. return 0;
  638. err_destroy_data:
  639. rpc_destroy_pipe_data(cn->cn_pipe);
  640. err:
  641. kfree(cn);
  642. printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
  643. ret);
  644. return ret;
  645. }
  646. static void
  647. nfsd4_remove_cld_pipe(struct net *net)
  648. {
  649. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  650. struct cld_net *cn = nn->cld_net;
  651. nfsd4_cld_unregister_net(net, cn->cn_pipe);
  652. rpc_destroy_pipe_data(cn->cn_pipe);
  653. kfree(nn->cld_net);
  654. nn->cld_net = NULL;
  655. }
  656. static struct cld_upcall *
  657. alloc_cld_upcall(struct cld_net *cn)
  658. {
  659. struct cld_upcall *new, *tmp;
  660. new = kzalloc(sizeof(*new), GFP_KERNEL);
  661. if (!new)
  662. return new;
  663. /* FIXME: hard cap on number in flight? */
  664. restart_search:
  665. spin_lock(&cn->cn_lock);
  666. list_for_each_entry(tmp, &cn->cn_list, cu_list) {
  667. if (tmp->cu_msg.cm_xid == cn->cn_xid) {
  668. cn->cn_xid++;
  669. spin_unlock(&cn->cn_lock);
  670. goto restart_search;
  671. }
  672. }
  673. new->cu_task = current;
  674. new->cu_msg.cm_vers = CLD_UPCALL_VERSION;
  675. put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid);
  676. new->cu_net = cn;
  677. list_add(&new->cu_list, &cn->cn_list);
  678. spin_unlock(&cn->cn_lock);
  679. dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid);
  680. return new;
  681. }
  682. static void
  683. free_cld_upcall(struct cld_upcall *victim)
  684. {
  685. struct cld_net *cn = victim->cu_net;
  686. spin_lock(&cn->cn_lock);
  687. list_del(&victim->cu_list);
  688. spin_unlock(&cn->cn_lock);
  689. kfree(victim);
  690. }
  691. /* Ask daemon to create a new record */
  692. static void
  693. nfsd4_cld_create(struct nfs4_client *clp)
  694. {
  695. int ret;
  696. struct cld_upcall *cup;
  697. /* FIXME: determine net from clp */
  698. struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
  699. struct cld_net *cn = nn->cld_net;
  700. /* Don't upcall if it's already stored */
  701. if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
  702. return;
  703. cup = alloc_cld_upcall(cn);
  704. if (!cup) {
  705. ret = -ENOMEM;
  706. goto out_err;
  707. }
  708. cup->cu_msg.cm_cmd = Cld_Create;
  709. cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
  710. memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
  711. clp->cl_name.len);
  712. ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
  713. if (!ret) {
  714. ret = cup->cu_msg.cm_status;
  715. set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
  716. }
  717. free_cld_upcall(cup);
  718. out_err:
  719. if (ret)
  720. printk(KERN_ERR "NFSD: Unable to create client "
  721. "record on stable storage: %d\n", ret);
  722. }
  723. /* Ask daemon to create a new record */
  724. static void
  725. nfsd4_cld_remove(struct nfs4_client *clp)
  726. {
  727. int ret;
  728. struct cld_upcall *cup;
  729. /* FIXME: determine net from clp */
  730. struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
  731. struct cld_net *cn = nn->cld_net;
  732. /* Don't upcall if it's already removed */
  733. if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
  734. return;
  735. cup = alloc_cld_upcall(cn);
  736. if (!cup) {
  737. ret = -ENOMEM;
  738. goto out_err;
  739. }
  740. cup->cu_msg.cm_cmd = Cld_Remove;
  741. cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
  742. memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
  743. clp->cl_name.len);
  744. ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
  745. if (!ret) {
  746. ret = cup->cu_msg.cm_status;
  747. clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
  748. }
  749. free_cld_upcall(cup);
  750. out_err:
  751. if (ret)
  752. printk(KERN_ERR "NFSD: Unable to remove client "
  753. "record from stable storage: %d\n", ret);
  754. }
  755. /* Check for presence of a record, and update its timestamp */
  756. static int
  757. nfsd4_cld_check(struct nfs4_client *clp)
  758. {
  759. int ret;
  760. struct cld_upcall *cup;
  761. /* FIXME: determine net from clp */
  762. struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
  763. struct cld_net *cn = nn->cld_net;
  764. /* Don't upcall if one was already stored during this grace pd */
  765. if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
  766. return 0;
  767. cup = alloc_cld_upcall(cn);
  768. if (!cup) {
  769. printk(KERN_ERR "NFSD: Unable to check client record on "
  770. "stable storage: %d\n", -ENOMEM);
  771. return -ENOMEM;
  772. }
  773. cup->cu_msg.cm_cmd = Cld_Check;
  774. cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
  775. memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
  776. clp->cl_name.len);
  777. ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
  778. if (!ret) {
  779. ret = cup->cu_msg.cm_status;
  780. set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
  781. }
  782. free_cld_upcall(cup);
  783. return ret;
  784. }
  785. static void
  786. nfsd4_cld_grace_done(struct net *net, time_t boot_time)
  787. {
  788. int ret;
  789. struct cld_upcall *cup;
  790. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  791. struct cld_net *cn = nn->cld_net;
  792. cup = alloc_cld_upcall(cn);
  793. if (!cup) {
  794. ret = -ENOMEM;
  795. goto out_err;
  796. }
  797. cup->cu_msg.cm_cmd = Cld_GraceDone;
  798. cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time;
  799. ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
  800. if (!ret)
  801. ret = cup->cu_msg.cm_status;
  802. free_cld_upcall(cup);
  803. out_err:
  804. if (ret)
  805. printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
  806. }
  807. static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
  808. .init = nfsd4_init_cld_pipe,
  809. .exit = nfsd4_remove_cld_pipe,
  810. .create = nfsd4_cld_create,
  811. .remove = nfsd4_cld_remove,
  812. .check = nfsd4_cld_check,
  813. .grace_done = nfsd4_cld_grace_done,
  814. };
  815. /* upcall via usermodehelper */
  816. static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
  817. module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
  818. S_IRUGO|S_IWUSR);
  819. MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
  820. static bool cltrack_legacy_disable;
  821. module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
  822. MODULE_PARM_DESC(cltrack_legacy_disable,
  823. "Disable legacy recoverydir conversion. Default: false");
  824. #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
  825. #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
  826. static char *
  827. nfsd4_cltrack_legacy_topdir(void)
  828. {
  829. int copied;
  830. size_t len;
  831. char *result;
  832. if (cltrack_legacy_disable)
  833. return NULL;
  834. len = strlen(LEGACY_TOPDIR_ENV_PREFIX) +
  835. strlen(nfs4_recoverydir()) + 1;
  836. result = kmalloc(len, GFP_KERNEL);
  837. if (!result)
  838. return result;
  839. copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s",
  840. nfs4_recoverydir());
  841. if (copied >= len) {
  842. /* just return nothing if output was truncated */
  843. kfree(result);
  844. return NULL;
  845. }
  846. return result;
  847. }
  848. static char *
  849. nfsd4_cltrack_legacy_recdir(const char *recdir)
  850. {
  851. int copied;
  852. size_t len;
  853. char *result;
  854. if (cltrack_legacy_disable)
  855. return NULL;
  856. /* +1 is for '/' between "topdir" and "recdir" */
  857. len = strlen(LEGACY_RECDIR_ENV_PREFIX) +
  858. strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN;
  859. result = kmalloc(len, GFP_KERNEL);
  860. if (!result)
  861. return result;
  862. copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/%s",
  863. nfs4_recoverydir(), recdir);
  864. if (copied >= len) {
  865. /* just return nothing if output was truncated */
  866. kfree(result);
  867. return NULL;
  868. }
  869. return result;
  870. }
  871. static int
  872. nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *legacy)
  873. {
  874. char *envp[2];
  875. char *argv[4];
  876. int ret;
  877. if (unlikely(!cltrack_prog[0])) {
  878. dprintk("%s: cltrack_prog is disabled\n", __func__);
  879. return -EACCES;
  880. }
  881. dprintk("%s: cmd: %s\n", __func__, cmd);
  882. dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
  883. dprintk("%s: legacy: %s\n", __func__, legacy ? legacy : "(null)");
  884. envp[0] = legacy;
  885. envp[1] = NULL;
  886. argv[0] = (char *)cltrack_prog;
  887. argv[1] = cmd;
  888. argv[2] = arg;
  889. argv[3] = NULL;
  890. ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
  891. /*
  892. * Disable the upcall mechanism if we're getting an ENOENT or EACCES
  893. * error. The admin can re-enable it on the fly by using sysfs
  894. * once the problem has been fixed.
  895. */
  896. if (ret == -ENOENT || ret == -EACCES) {
  897. dprintk("NFSD: %s was not found or isn't executable (%d). "
  898. "Setting cltrack_prog to blank string!",
  899. cltrack_prog, ret);
  900. cltrack_prog[0] = '\0';
  901. }
  902. dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret);
  903. return ret;
  904. }
  905. static char *
  906. bin_to_hex_dup(const unsigned char *src, int srclen)
  907. {
  908. int i;
  909. char *buf, *hex;
  910. /* +1 for terminating NULL */
  911. buf = kmalloc((srclen * 2) + 1, GFP_KERNEL);
  912. if (!buf)
  913. return buf;
  914. hex = buf;
  915. for (i = 0; i < srclen; i++) {
  916. sprintf(hex, "%2.2x", *src++);
  917. hex += 2;
  918. }
  919. return buf;
  920. }
  921. static int
  922. nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net)
  923. {
  924. return nfsd4_umh_cltrack_upcall("init", NULL, NULL);
  925. }
  926. static void
  927. nfsd4_umh_cltrack_create(struct nfs4_client *clp)
  928. {
  929. char *hexid;
  930. hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
  931. if (!hexid) {
  932. dprintk("%s: can't allocate memory for upcall!\n", __func__);
  933. return;
  934. }
  935. nfsd4_umh_cltrack_upcall("create", hexid, NULL);
  936. kfree(hexid);
  937. }
  938. static void
  939. nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
  940. {
  941. char *hexid;
  942. hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
  943. if (!hexid) {
  944. dprintk("%s: can't allocate memory for upcall!\n", __func__);
  945. return;
  946. }
  947. nfsd4_umh_cltrack_upcall("remove", hexid, NULL);
  948. kfree(hexid);
  949. }
  950. static int
  951. nfsd4_umh_cltrack_check(struct nfs4_client *clp)
  952. {
  953. int ret;
  954. char *hexid, *legacy;
  955. hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
  956. if (!hexid) {
  957. dprintk("%s: can't allocate memory for upcall!\n", __func__);
  958. return -ENOMEM;
  959. }
  960. legacy = nfsd4_cltrack_legacy_recdir(clp->cl_recdir);
  961. ret = nfsd4_umh_cltrack_upcall("check", hexid, legacy);
  962. kfree(legacy);
  963. kfree(hexid);
  964. return ret;
  965. }
  966. static void
  967. nfsd4_umh_cltrack_grace_done(struct net __attribute__((unused)) *net,
  968. time_t boot_time)
  969. {
  970. char *legacy;
  971. char timestr[22]; /* FIXME: better way to determine max size? */
  972. sprintf(timestr, "%ld", boot_time);
  973. legacy = nfsd4_cltrack_legacy_topdir();
  974. nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy);
  975. kfree(legacy);
  976. }
  977. static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {
  978. .init = nfsd4_umh_cltrack_init,
  979. .exit = NULL,
  980. .create = nfsd4_umh_cltrack_create,
  981. .remove = nfsd4_umh_cltrack_remove,
  982. .check = nfsd4_umh_cltrack_check,
  983. .grace_done = nfsd4_umh_cltrack_grace_done,
  984. };
  985. int
  986. nfsd4_client_tracking_init(struct net *net)
  987. {
  988. int status;
  989. struct path path;
  990. /* just run the init if it the method is already decided */
  991. if (client_tracking_ops)
  992. goto do_init;
  993. /*
  994. * First, try a UMH upcall. It should succeed or fail quickly, so
  995. * there's little harm in trying that first.
  996. */
  997. client_tracking_ops = &nfsd4_umh_tracking_ops;
  998. status = client_tracking_ops->init(net);
  999. if (!status)
  1000. return status;
  1001. /*
  1002. * See if the recoverydir exists and is a directory. If it is,
  1003. * then use the legacy ops.
  1004. */
  1005. client_tracking_ops = &nfsd4_legacy_tracking_ops;
  1006. status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
  1007. if (!status) {
  1008. status = S_ISDIR(path.dentry->d_inode->i_mode);
  1009. path_put(&path);
  1010. if (status)
  1011. goto do_init;
  1012. }
  1013. /* Finally, try to use nfsdcld */
  1014. client_tracking_ops = &nfsd4_cld_tracking_ops;
  1015. printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be "
  1016. "removed in 3.10. Please transition to using "
  1017. "nfsdcltrack.\n");
  1018. do_init:
  1019. status = client_tracking_ops->init(net);
  1020. if (status) {
  1021. printk(KERN_WARNING "NFSD: Unable to initialize client "
  1022. "recovery tracking! (%d)\n", status);
  1023. client_tracking_ops = NULL;
  1024. }
  1025. return status;
  1026. }
  1027. void
  1028. nfsd4_client_tracking_exit(struct net *net)
  1029. {
  1030. if (client_tracking_ops) {
  1031. if (client_tracking_ops->exit)
  1032. client_tracking_ops->exit(net);
  1033. client_tracking_ops = NULL;
  1034. }
  1035. }
  1036. void
  1037. nfsd4_client_record_create(struct nfs4_client *clp)
  1038. {
  1039. if (client_tracking_ops)
  1040. client_tracking_ops->create(clp);
  1041. }
  1042. void
  1043. nfsd4_client_record_remove(struct nfs4_client *clp)
  1044. {
  1045. if (client_tracking_ops)
  1046. client_tracking_ops->remove(clp);
  1047. }
  1048. int
  1049. nfsd4_client_record_check(struct nfs4_client *clp)
  1050. {
  1051. if (client_tracking_ops)
  1052. return client_tracking_ops->check(clp);
  1053. return -EOPNOTSUPP;
  1054. }
  1055. void
  1056. nfsd4_record_grace_done(struct net *net, time_t boot_time)
  1057. {
  1058. if (client_tracking_ops)
  1059. client_tracking_ops->grace_done(net, boot_time);
  1060. }
  1061. static int
  1062. rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
  1063. {
  1064. struct super_block *sb = ptr;
  1065. struct net *net = sb->s_fs_info;
  1066. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  1067. struct cld_net *cn = nn->cld_net;
  1068. struct dentry *dentry;
  1069. int ret = 0;
  1070. if (!try_module_get(THIS_MODULE))
  1071. return 0;
  1072. if (!cn) {
  1073. module_put(THIS_MODULE);
  1074. return 0;
  1075. }
  1076. switch (event) {
  1077. case RPC_PIPEFS_MOUNT:
  1078. dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
  1079. if (IS_ERR(dentry)) {
  1080. ret = PTR_ERR(dentry);
  1081. break;
  1082. }
  1083. cn->cn_pipe->dentry = dentry;
  1084. break;
  1085. case RPC_PIPEFS_UMOUNT:
  1086. if (cn->cn_pipe->dentry)
  1087. nfsd4_cld_unregister_sb(cn->cn_pipe);
  1088. break;
  1089. default:
  1090. ret = -ENOTSUPP;
  1091. break;
  1092. }
  1093. module_put(THIS_MODULE);
  1094. return ret;
  1095. }
  1096. static struct notifier_block nfsd4_cld_block = {
  1097. .notifier_call = rpc_pipefs_event,
  1098. };
  1099. int
  1100. register_cld_notifier(void)
  1101. {
  1102. return rpc_pipefs_notifier_register(&nfsd4_cld_block);
  1103. }
  1104. void
  1105. unregister_cld_notifier(void)
  1106. {
  1107. rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
  1108. }