client.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. /* client.c: NFS client sharing and management code
  2. *
  3. * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/config.h>
  12. #include <linux/module.h>
  13. #include <linux/init.h>
  14. #include <linux/time.h>
  15. #include <linux/kernel.h>
  16. #include <linux/mm.h>
  17. #include <linux/string.h>
  18. #include <linux/stat.h>
  19. #include <linux/errno.h>
  20. #include <linux/unistd.h>
  21. #include <linux/sunrpc/clnt.h>
  22. #include <linux/sunrpc/stats.h>
  23. #include <linux/sunrpc/metrics.h>
  24. #include <linux/nfs_fs.h>
  25. #include <linux/nfs_mount.h>
  26. #include <linux/nfs4_mount.h>
  27. #include <linux/lockd/bind.h>
  28. #include <linux/smp_lock.h>
  29. #include <linux/seq_file.h>
  30. #include <linux/mount.h>
  31. #include <linux/nfs_idmap.h>
  32. #include <linux/vfs.h>
  33. #include <linux/inet.h>
  34. #include <linux/nfs_xdr.h>
  35. #include <asm/system.h>
  36. #include "nfs4_fs.h"
  37. #include "callback.h"
  38. #include "delegation.h"
  39. #include "iostat.h"
  40. #include "internal.h"
  41. #define NFSDBG_FACILITY NFSDBG_CLIENT
  42. static DEFINE_SPINLOCK(nfs_client_lock);
  43. static LIST_HEAD(nfs_client_list);
  44. static LIST_HEAD(nfs_volume_list);
  45. static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
  46. /*
  47. * RPC cruft for NFS
  48. */
  49. static struct rpc_version *nfs_version[5] = {
  50. [2] = &nfs_version2,
  51. #ifdef CONFIG_NFS_V3
  52. [3] = &nfs_version3,
  53. #endif
  54. #ifdef CONFIG_NFS_V4
  55. [4] = &nfs_version4,
  56. #endif
  57. };
  58. struct rpc_program nfs_program = {
  59. .name = "nfs",
  60. .number = NFS_PROGRAM,
  61. .nrvers = ARRAY_SIZE(nfs_version),
  62. .version = nfs_version,
  63. .stats = &nfs_rpcstat,
  64. .pipe_dir_name = "/nfs",
  65. };
  66. struct rpc_stat nfs_rpcstat = {
  67. .program = &nfs_program
  68. };
  69. #ifdef CONFIG_NFS_V3_ACL
  70. static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
  71. static struct rpc_version * nfsacl_version[] = {
  72. [3] = &nfsacl_version3,
  73. };
  74. struct rpc_program nfsacl_program = {
  75. .name = "nfsacl",
  76. .number = NFS_ACL_PROGRAM,
  77. .nrvers = ARRAY_SIZE(nfsacl_version),
  78. .version = nfsacl_version,
  79. .stats = &nfsacl_rpcstat,
  80. };
  81. #endif /* CONFIG_NFS_V3_ACL */
  82. /*
  83. * Allocate a shared client record
  84. *
  85. * Since these are allocated/deallocated very rarely, we don't
  86. * bother putting them in a slab cache...
  87. */
  88. static struct nfs_client *nfs_alloc_client(const char *hostname,
  89. const struct sockaddr_in *addr,
  90. int nfsversion)
  91. {
  92. struct nfs_client *clp;
  93. int error;
  94. if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
  95. goto error_0;
  96. error = rpciod_up();
  97. if (error < 0) {
  98. dprintk("%s: couldn't start rpciod! Error = %d\n",
  99. __FUNCTION__, error);
  100. goto error_1;
  101. }
  102. __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
  103. if (nfsversion == 4) {
  104. if (nfs_callback_up() < 0)
  105. goto error_2;
  106. __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
  107. }
  108. atomic_set(&clp->cl_count, 1);
  109. clp->cl_cons_state = NFS_CS_INITING;
  110. clp->cl_nfsversion = nfsversion;
  111. memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
  112. if (hostname) {
  113. clp->cl_hostname = kstrdup(hostname, GFP_KERNEL);
  114. if (!clp->cl_hostname)
  115. goto error_3;
  116. }
  117. INIT_LIST_HEAD(&clp->cl_superblocks);
  118. clp->cl_rpcclient = ERR_PTR(-EINVAL);
  119. #ifdef CONFIG_NFS_V4
  120. init_rwsem(&clp->cl_sem);
  121. INIT_LIST_HEAD(&clp->cl_delegations);
  122. INIT_LIST_HEAD(&clp->cl_state_owners);
  123. INIT_LIST_HEAD(&clp->cl_unused);
  124. spin_lock_init(&clp->cl_lock);
  125. INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
  126. rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
  127. clp->cl_boot_time = CURRENT_TIME;
  128. clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
  129. #endif
  130. return clp;
  131. error_3:
  132. if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
  133. nfs_callback_down();
  134. error_2:
  135. rpciod_down();
  136. __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
  137. error_1:
  138. kfree(clp);
  139. error_0:
  140. return NULL;
  141. }
  142. static void nfs4_shutdown_client(struct nfs_client *clp)
  143. {
  144. #ifdef CONFIG_NFS_V4
  145. if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
  146. nfs4_kill_renewd(clp);
  147. while (!list_empty(&clp->cl_unused)) {
  148. struct nfs4_state_owner *sp;
  149. sp = list_entry(clp->cl_unused.next,
  150. struct nfs4_state_owner,
  151. so_list);
  152. list_del(&sp->so_list);
  153. kfree(sp);
  154. }
  155. BUG_ON(!list_empty(&clp->cl_state_owners));
  156. if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
  157. nfs_idmap_delete(clp);
  158. #endif
  159. }
  160. /*
  161. * Destroy a shared client record
  162. */
  163. static void nfs_free_client(struct nfs_client *clp)
  164. {
  165. dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion);
  166. nfs4_shutdown_client(clp);
  167. /* -EIO all pending I/O */
  168. if (!IS_ERR(clp->cl_rpcclient))
  169. rpc_shutdown_client(clp->cl_rpcclient);
  170. if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
  171. nfs_callback_down();
  172. if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
  173. rpciod_down();
  174. kfree(clp->cl_hostname);
  175. kfree(clp);
  176. dprintk("<-- nfs_free_client()\n");
  177. }
  178. /*
  179. * Release a reference to a shared client record
  180. */
  181. void nfs_put_client(struct nfs_client *clp)
  182. {
  183. if (!clp)
  184. return;
  185. dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count));
  186. if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
  187. list_del(&clp->cl_share_link);
  188. spin_unlock(&nfs_client_lock);
  189. BUG_ON(!list_empty(&clp->cl_superblocks));
  190. nfs_free_client(clp);
  191. }
  192. }
  193. /*
  194. * Find a client by address
  195. * - caller must hold nfs_client_lock
  196. */
  197. static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
  198. {
  199. struct nfs_client *clp;
  200. list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
  201. /* Different NFS versions cannot share the same nfs_client */
  202. if (clp->cl_nfsversion != nfsversion)
  203. continue;
  204. if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr,
  205. sizeof(clp->cl_addr.sin_addr)) != 0)
  206. continue;
  207. if (clp->cl_addr.sin_port == addr->sin_port)
  208. goto found;
  209. }
  210. return NULL;
  211. found:
  212. atomic_inc(&clp->cl_count);
  213. return clp;
  214. }
  215. /*
  216. * Find a client by IP address and protocol version
  217. * - returns NULL if no such client
  218. */
  219. struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
  220. {
  221. struct nfs_client *clp;
  222. spin_lock(&nfs_client_lock);
  223. clp = __nfs_find_client(addr, nfsversion);
  224. spin_unlock(&nfs_client_lock);
  225. BUG_ON(clp && clp->cl_cons_state == 0);
  226. return clp;
  227. }
  228. /*
  229. * Look up a client by IP address and protocol version
  230. * - creates a new record if one doesn't yet exist
  231. */
  232. static struct nfs_client *nfs_get_client(const char *hostname,
  233. const struct sockaddr_in *addr,
  234. int nfsversion)
  235. {
  236. struct nfs_client *clp, *new = NULL;
  237. int error;
  238. dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n",
  239. hostname ?: "", NIPQUAD(addr->sin_addr),
  240. addr->sin_port, nfsversion);
  241. /* see if the client already exists */
  242. do {
  243. spin_lock(&nfs_client_lock);
  244. clp = __nfs_find_client(addr, nfsversion);
  245. if (clp)
  246. goto found_client;
  247. if (new)
  248. goto install_client;
  249. spin_unlock(&nfs_client_lock);
  250. new = nfs_alloc_client(hostname, addr, nfsversion);
  251. } while (new);
  252. return ERR_PTR(-ENOMEM);
  253. /* install a new client and return with it unready */
  254. install_client:
  255. clp = new;
  256. list_add(&clp->cl_share_link, &nfs_client_list);
  257. spin_unlock(&nfs_client_lock);
  258. dprintk("--> nfs_get_client() = %p [new]\n", clp);
  259. return clp;
  260. /* found an existing client
  261. * - make sure it's ready before returning
  262. */
  263. found_client:
  264. spin_unlock(&nfs_client_lock);
  265. if (new)
  266. nfs_free_client(new);
  267. if (clp->cl_cons_state == NFS_CS_INITING) {
  268. DECLARE_WAITQUEUE(myself, current);
  269. add_wait_queue(&nfs_client_active_wq, &myself);
  270. for (;;) {
  271. set_current_state(TASK_INTERRUPTIBLE);
  272. if (signal_pending(current) ||
  273. clp->cl_cons_state > NFS_CS_READY)
  274. break;
  275. schedule();
  276. }
  277. remove_wait_queue(&nfs_client_active_wq, &myself);
  278. if (signal_pending(current)) {
  279. nfs_put_client(clp);
  280. return ERR_PTR(-ERESTARTSYS);
  281. }
  282. }
  283. if (clp->cl_cons_state < NFS_CS_READY) {
  284. error = clp->cl_cons_state;
  285. nfs_put_client(clp);
  286. return ERR_PTR(error);
  287. }
  288. BUG_ON(clp->cl_cons_state != NFS_CS_READY);
  289. dprintk("--> nfs_get_client() = %p [share]\n", clp);
  290. return clp;
  291. }
  292. /*
  293. * Mark a server as ready or failed
  294. */
  295. static void nfs_mark_client_ready(struct nfs_client *clp, int state)
  296. {
  297. clp->cl_cons_state = state;
  298. wake_up_all(&nfs_client_active_wq);
  299. }
  300. /*
  301. * Initialise the timeout values for a connection
  302. */
  303. static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
  304. unsigned int timeo, unsigned int retrans)
  305. {
  306. to->to_initval = timeo * HZ / 10;
  307. to->to_retries = retrans;
  308. if (!to->to_retries)
  309. to->to_retries = 2;
  310. switch (proto) {
  311. case IPPROTO_TCP:
  312. if (!to->to_initval)
  313. to->to_initval = 60 * HZ;
  314. if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
  315. to->to_initval = NFS_MAX_TCP_TIMEOUT;
  316. to->to_increment = to->to_initval;
  317. to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
  318. to->to_exponential = 0;
  319. break;
  320. case IPPROTO_UDP:
  321. default:
  322. if (!to->to_initval)
  323. to->to_initval = 11 * HZ / 10;
  324. if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
  325. to->to_initval = NFS_MAX_UDP_TIMEOUT;
  326. to->to_maxval = NFS_MAX_UDP_TIMEOUT;
  327. to->to_exponential = 1;
  328. break;
  329. }
  330. }
  331. /*
  332. * Create an RPC client handle
  333. */
  334. static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
  335. unsigned int timeo,
  336. unsigned int retrans,
  337. rpc_authflavor_t flavor)
  338. {
  339. struct rpc_timeout timeparms;
  340. struct rpc_clnt *clnt = NULL;
  341. struct rpc_create_args args = {
  342. .protocol = proto,
  343. .address = (struct sockaddr *)&clp->cl_addr,
  344. .addrsize = sizeof(clp->cl_addr),
  345. .timeout = &timeparms,
  346. .servername = clp->cl_hostname,
  347. .program = &nfs_program,
  348. .version = clp->rpc_ops->version,
  349. .authflavor = flavor,
  350. };
  351. if (!IS_ERR(clp->cl_rpcclient))
  352. return 0;
  353. nfs_init_timeout_values(&timeparms, proto, timeo, retrans);
  354. clp->retrans_timeo = timeparms.to_initval;
  355. clp->retrans_count = timeparms.to_retries;
  356. clnt = rpc_create(&args);
  357. if (IS_ERR(clnt)) {
  358. dprintk("%s: cannot create RPC client. Error = %ld\n",
  359. __FUNCTION__, PTR_ERR(clnt));
  360. return PTR_ERR(clnt);
  361. }
  362. clp->cl_rpcclient = clnt;
  363. return 0;
  364. }
  365. /*
  366. * Version 2 or 3 client destruction
  367. */
  368. static void nfs_destroy_server(struct nfs_server *server)
  369. {
  370. if (!IS_ERR(server->client_acl))
  371. rpc_shutdown_client(server->client_acl);
  372. if (!(server->flags & NFS_MOUNT_NONLM))
  373. lockd_down(); /* release rpc.lockd */
  374. }
  375. /*
  376. * Version 2 or 3 lockd setup
  377. */
  378. static int nfs_start_lockd(struct nfs_server *server)
  379. {
  380. int error = 0;
  381. if (server->nfs_client->cl_nfsversion > 3)
  382. goto out;
  383. if (server->flags & NFS_MOUNT_NONLM)
  384. goto out;
  385. error = lockd_up((server->flags & NFS_MOUNT_TCP) ?
  386. IPPROTO_TCP : IPPROTO_UDP);
  387. if (error < 0)
  388. server->flags |= NFS_MOUNT_NONLM;
  389. else
  390. server->destroy = nfs_destroy_server;
  391. out:
  392. return error;
  393. }
  394. /*
  395. * Initialise an NFSv3 ACL client connection
  396. */
  397. #ifdef CONFIG_NFS_V3_ACL
  398. static void nfs_init_server_aclclient(struct nfs_server *server)
  399. {
  400. if (server->nfs_client->cl_nfsversion != 3)
  401. goto out_noacl;
  402. if (server->flags & NFS_MOUNT_NOACL)
  403. goto out_noacl;
  404. server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
  405. if (IS_ERR(server->client_acl))
  406. goto out_noacl;
  407. /* No errors! Assume that Sun nfsacls are supported */
  408. server->caps |= NFS_CAP_ACLS;
  409. return;
  410. out_noacl:
  411. server->caps &= ~NFS_CAP_ACLS;
  412. }
  413. #else
  414. static inline void nfs_init_server_aclclient(struct nfs_server *server)
  415. {
  416. server->flags &= ~NFS_MOUNT_NOACL;
  417. server->caps &= ~NFS_CAP_ACLS;
  418. }
  419. #endif
  420. /*
  421. * Create a general RPC client
  422. */
  423. static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour)
  424. {
  425. struct nfs_client *clp = server->nfs_client;
  426. server->client = rpc_clone_client(clp->cl_rpcclient);
  427. if (IS_ERR(server->client)) {
  428. dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__);
  429. return PTR_ERR(server->client);
  430. }
  431. if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) {
  432. struct rpc_auth *auth;
  433. auth = rpcauth_create(pseudoflavour, server->client);
  434. if (IS_ERR(auth)) {
  435. dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
  436. return PTR_ERR(auth);
  437. }
  438. }
  439. server->client->cl_softrtry = 0;
  440. if (server->flags & NFS_MOUNT_SOFT)
  441. server->client->cl_softrtry = 1;
  442. server->client->cl_intr = 0;
  443. if (server->flags & NFS4_MOUNT_INTR)
  444. server->client->cl_intr = 1;
  445. return 0;
  446. }
  447. /*
  448. * Initialise an NFS2 or NFS3 client
  449. */
  450. static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data)
  451. {
  452. int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
  453. int error;
  454. if (clp->cl_cons_state == NFS_CS_READY) {
  455. /* the client is already initialised */
  456. dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp);
  457. return 0;
  458. }
  459. /* Check NFS protocol revision and initialize RPC op vector */
  460. clp->rpc_ops = &nfs_v2_clientops;
  461. #ifdef CONFIG_NFS_V3
  462. if (clp->cl_nfsversion == 3)
  463. clp->rpc_ops = &nfs_v3_clientops;
  464. #endif
  465. /*
  466. * Create a client RPC handle for doing FSSTAT with UNIX auth only
  467. * - RFC 2623, sec 2.3.2
  468. */
  469. error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
  470. RPC_AUTH_UNIX);
  471. if (error < 0)
  472. goto error;
  473. nfs_mark_client_ready(clp, NFS_CS_READY);
  474. return 0;
  475. error:
  476. nfs_mark_client_ready(clp, error);
  477. dprintk("<-- nfs_init_client() = xerror %d\n", error);
  478. return error;
  479. }
  480. /*
  481. * Create a version 2 or 3 client
  482. */
  483. static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data)
  484. {
  485. struct nfs_client *clp;
  486. int error, nfsvers = 2;
  487. dprintk("--> nfs_init_server()\n");
  488. #ifdef CONFIG_NFS_V3
  489. if (data->flags & NFS_MOUNT_VER3)
  490. nfsvers = 3;
  491. #endif
  492. /* Allocate or find a client reference we can use */
  493. clp = nfs_get_client(data->hostname, &data->addr, nfsvers);
  494. if (IS_ERR(clp)) {
  495. dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
  496. return PTR_ERR(clp);
  497. }
  498. error = nfs_init_client(clp, data);
  499. if (error < 0)
  500. goto error;
  501. server->nfs_client = clp;
  502. /* Initialise the client representation from the mount data */
  503. server->flags = data->flags & NFS_MOUNT_FLAGMASK;
  504. if (data->rsize)
  505. server->rsize = nfs_block_size(data->rsize, NULL);
  506. if (data->wsize)
  507. server->wsize = nfs_block_size(data->wsize, NULL);
  508. server->acregmin = data->acregmin * HZ;
  509. server->acregmax = data->acregmax * HZ;
  510. server->acdirmin = data->acdirmin * HZ;
  511. server->acdirmax = data->acdirmax * HZ;
  512. /* Start lockd here, before we might error out */
  513. error = nfs_start_lockd(server);
  514. if (error < 0)
  515. goto error;
  516. error = nfs_init_server_rpcclient(server, data->pseudoflavor);
  517. if (error < 0)
  518. goto error;
  519. server->namelen = data->namlen;
  520. /* Create a client RPC handle for the NFSv3 ACL management interface */
  521. nfs_init_server_aclclient(server);
  522. if (clp->cl_nfsversion == 3) {
  523. if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
  524. server->namelen = NFS3_MAXNAMLEN;
  525. server->caps |= NFS_CAP_READDIRPLUS;
  526. } else {
  527. if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
  528. server->namelen = NFS2_MAXNAMLEN;
  529. }
  530. dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
  531. return 0;
  532. error:
  533. server->nfs_client = NULL;
  534. nfs_put_client(clp);
  535. dprintk("<-- nfs_init_server() = xerror %d\n", error);
  536. return error;
  537. }
  538. /*
  539. * Load up the server record from information gained in an fsinfo record
  540. */
  541. static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo)
  542. {
  543. unsigned long max_rpc_payload;
  544. /* Work out a lot of parameters */
  545. if (server->rsize == 0)
  546. server->rsize = nfs_block_size(fsinfo->rtpref, NULL);
  547. if (server->wsize == 0)
  548. server->wsize = nfs_block_size(fsinfo->wtpref, NULL);
  549. if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax)
  550. server->rsize = nfs_block_size(fsinfo->rtmax, NULL);
  551. if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax)
  552. server->wsize = nfs_block_size(fsinfo->wtmax, NULL);
  553. max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
  554. if (server->rsize > max_rpc_payload)
  555. server->rsize = max_rpc_payload;
  556. if (server->rsize > NFS_MAX_FILE_IO_SIZE)
  557. server->rsize = NFS_MAX_FILE_IO_SIZE;
  558. server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
  559. server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
  560. if (server->wsize > max_rpc_payload)
  561. server->wsize = max_rpc_payload;
  562. if (server->wsize > NFS_MAX_FILE_IO_SIZE)
  563. server->wsize = NFS_MAX_FILE_IO_SIZE;
  564. server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
  565. server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
  566. server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
  567. if (server->dtsize > PAGE_CACHE_SIZE)
  568. server->dtsize = PAGE_CACHE_SIZE;
  569. if (server->dtsize > server->rsize)
  570. server->dtsize = server->rsize;
  571. if (server->flags & NFS_MOUNT_NOAC) {
  572. server->acregmin = server->acregmax = 0;
  573. server->acdirmin = server->acdirmax = 0;
  574. }
  575. server->maxfilesize = fsinfo->maxfilesize;
  576. /* We're airborne Set socket buffersize */
  577. rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
  578. }
  579. /*
  580. * Probe filesystem information, including the FSID on v2/v3
  581. */
  582. static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
  583. {
  584. struct nfs_fsinfo fsinfo;
  585. struct nfs_client *clp = server->nfs_client;
  586. int error;
  587. dprintk("--> nfs_probe_fsinfo()\n");
  588. if (clp->rpc_ops->set_capabilities != NULL) {
  589. error = clp->rpc_ops->set_capabilities(server, mntfh);
  590. if (error < 0)
  591. goto out_error;
  592. }
  593. fsinfo.fattr = fattr;
  594. nfs_fattr_init(fattr);
  595. error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
  596. if (error < 0)
  597. goto out_error;
  598. nfs_server_set_fsinfo(server, &fsinfo);
  599. /* Get some general file system info */
  600. if (server->namelen == 0) {
  601. struct nfs_pathconf pathinfo;
  602. pathinfo.fattr = fattr;
  603. nfs_fattr_init(fattr);
  604. if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
  605. server->namelen = pathinfo.max_namelen;
  606. }
  607. dprintk("<-- nfs_probe_fsinfo() = 0\n");
  608. return 0;
  609. out_error:
  610. dprintk("nfs_probe_fsinfo: error = %d\n", -error);
  611. return error;
  612. }
  613. /*
  614. * Copy useful information when duplicating a server record
  615. */
  616. static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
  617. {
  618. target->flags = source->flags;
  619. target->acregmin = source->acregmin;
  620. target->acregmax = source->acregmax;
  621. target->acdirmin = source->acdirmin;
  622. target->acdirmax = source->acdirmax;
  623. target->caps = source->caps;
  624. }
  625. /*
  626. * Allocate and initialise a server record
  627. */
  628. static struct nfs_server *nfs_alloc_server(void)
  629. {
  630. struct nfs_server *server;
  631. server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
  632. if (!server)
  633. return NULL;
  634. server->client = server->client_acl = ERR_PTR(-EINVAL);
  635. /* Zero out the NFS state stuff */
  636. INIT_LIST_HEAD(&server->client_link);
  637. INIT_LIST_HEAD(&server->master_link);
  638. server->io_stats = nfs_alloc_iostats();
  639. if (!server->io_stats) {
  640. kfree(server);
  641. return NULL;
  642. }
  643. return server;
  644. }
  645. /*
  646. * Free up a server record
  647. */
  648. void nfs_free_server(struct nfs_server *server)
  649. {
  650. dprintk("--> nfs_free_server()\n");
  651. spin_lock(&nfs_client_lock);
  652. list_del(&server->client_link);
  653. list_del(&server->master_link);
  654. spin_unlock(&nfs_client_lock);
  655. if (server->destroy != NULL)
  656. server->destroy(server);
  657. if (!IS_ERR(server->client))
  658. rpc_shutdown_client(server->client);
  659. nfs_put_client(server->nfs_client);
  660. nfs_free_iostats(server->io_stats);
  661. kfree(server);
  662. nfs_release_automount_timer();
  663. dprintk("<-- nfs_free_server()\n");
  664. }
  665. /*
  666. * Create a version 2 or 3 volume record
  667. * - keyed on server and FSID
  668. */
  669. struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
  670. struct nfs_fh *mntfh)
  671. {
  672. struct nfs_server *server;
  673. struct nfs_fattr fattr;
  674. int error;
  675. server = nfs_alloc_server();
  676. if (!server)
  677. return ERR_PTR(-ENOMEM);
  678. /* Get a client representation */
  679. error = nfs_init_server(server, data);
  680. if (error < 0)
  681. goto error;
  682. BUG_ON(!server->nfs_client);
  683. BUG_ON(!server->nfs_client->rpc_ops);
  684. BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
  685. /* Probe the root fh to retrieve its FSID */
  686. error = nfs_probe_fsinfo(server, mntfh, &fattr);
  687. if (error < 0)
  688. goto error;
  689. if (!(fattr.valid & NFS_ATTR_FATTR)) {
  690. error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
  691. if (error < 0) {
  692. dprintk("nfs_create_server: getattr error = %d\n", -error);
  693. goto error;
  694. }
  695. }
  696. memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid));
  697. dprintk("Server FSID: %llx:%llx\n",
  698. (unsigned long long) server->fsid.major,
  699. (unsigned long long) server->fsid.minor);
  700. BUG_ON(!server->nfs_client);
  701. BUG_ON(!server->nfs_client->rpc_ops);
  702. BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
  703. spin_lock(&nfs_client_lock);
  704. list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
  705. list_add_tail(&server->master_link, &nfs_volume_list);
  706. spin_unlock(&nfs_client_lock);
  707. server->mount_time = jiffies;
  708. return server;
  709. error:
  710. nfs_free_server(server);
  711. return ERR_PTR(error);
  712. }
  713. #ifdef CONFIG_NFS_V4
  714. /*
  715. * Initialise an NFS4 client record
  716. */
  717. static int nfs4_init_client(struct nfs_client *clp,
  718. int proto, int timeo, int retrans,
  719. rpc_authflavor_t authflavour)
  720. {
  721. int error;
  722. if (clp->cl_cons_state == NFS_CS_READY) {
  723. /* the client is initialised already */
  724. dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
  725. return 0;
  726. }
  727. /* Check NFS protocol revision and initialize RPC op vector */
  728. clp->rpc_ops = &nfs_v4_clientops;
  729. error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour);
  730. if (error < 0)
  731. goto error;
  732. error = nfs_idmap_new(clp);
  733. if (error < 0) {
  734. dprintk("%s: failed to create idmapper. Error = %d\n",
  735. __FUNCTION__, error);
  736. goto error;
  737. }
  738. __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
  739. nfs_mark_client_ready(clp, NFS_CS_READY);
  740. return 0;
  741. error:
  742. nfs_mark_client_ready(clp, error);
  743. dprintk("<-- nfs4_init_client() = xerror %d\n", error);
  744. return error;
  745. }
  746. /*
  747. * Set up an NFS4 client
  748. */
  749. static int nfs4_set_client(struct nfs_server *server,
  750. const char *hostname, const struct sockaddr_in *addr,
  751. rpc_authflavor_t authflavour,
  752. int proto, int timeo, int retrans)
  753. {
  754. struct nfs_client *clp;
  755. int error;
  756. dprintk("--> nfs4_set_client()\n");
  757. /* Allocate or find a client reference we can use */
  758. clp = nfs_get_client(hostname, addr, 4);
  759. if (IS_ERR(clp)) {
  760. error = PTR_ERR(clp);
  761. goto error;
  762. }
  763. error = nfs4_init_client(clp, proto, timeo, retrans, authflavour);
  764. if (error < 0)
  765. goto error_put;
  766. server->nfs_client = clp;
  767. dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
  768. return 0;
  769. error_put:
  770. nfs_put_client(clp);
  771. error:
  772. dprintk("<-- nfs4_set_client() = xerror %d\n", error);
  773. return error;
  774. }
  775. /*
  776. * Create a version 4 volume record
  777. */
  778. static int nfs4_init_server(struct nfs_server *server,
  779. const struct nfs4_mount_data *data, rpc_authflavor_t authflavour)
  780. {
  781. int error;
  782. dprintk("--> nfs4_init_server()\n");
  783. /* Initialise the client representation from the mount data */
  784. server->flags = data->flags & NFS_MOUNT_FLAGMASK;
  785. server->caps |= NFS_CAP_ATOMIC_OPEN;
  786. if (data->rsize)
  787. server->rsize = nfs_block_size(data->rsize, NULL);
  788. if (data->wsize)
  789. server->wsize = nfs_block_size(data->wsize, NULL);
  790. server->acregmin = data->acregmin * HZ;
  791. server->acregmax = data->acregmax * HZ;
  792. server->acdirmin = data->acdirmin * HZ;
  793. server->acdirmax = data->acdirmax * HZ;
  794. error = nfs_init_server_rpcclient(server, authflavour);
  795. /* Done */
  796. dprintk("<-- nfs4_init_server() = %d\n", error);
  797. return error;
  798. }
  799. /*
  800. * Create a version 4 volume record
  801. * - keyed on server and FSID
  802. */
  803. struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
  804. const char *hostname,
  805. const struct sockaddr_in *addr,
  806. const char *mntpath,
  807. const char *ip_addr,
  808. rpc_authflavor_t authflavour,
  809. struct nfs_fh *mntfh)
  810. {
  811. struct nfs_fattr fattr;
  812. struct nfs_server *server;
  813. int error;
  814. dprintk("--> nfs4_create_server()\n");
  815. server = nfs_alloc_server();
  816. if (!server)
  817. return ERR_PTR(-ENOMEM);
  818. /* Get a client record */
  819. error = nfs4_set_client(server, hostname, addr, authflavour,
  820. data->proto, data->timeo, data->retrans);
  821. if (error < 0)
  822. goto error;
  823. /* set up the general RPC client */
  824. error = nfs4_init_server(server, data, authflavour);
  825. if (error < 0)
  826. goto error;
  827. BUG_ON(!server->nfs_client);
  828. BUG_ON(!server->nfs_client->rpc_ops);
  829. BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
  830. /* Probe the root fh to retrieve its FSID */
  831. error = nfs4_path_walk(server, mntfh, mntpath);
  832. if (error < 0)
  833. goto error;
  834. dprintk("Server FSID: %llx:%llx\n",
  835. (unsigned long long) server->fsid.major,
  836. (unsigned long long) server->fsid.minor);
  837. dprintk("Mount FH: %d\n", mntfh->size);
  838. error = nfs_probe_fsinfo(server, mntfh, &fattr);
  839. if (error < 0)
  840. goto error;
  841. BUG_ON(!server->nfs_client);
  842. BUG_ON(!server->nfs_client->rpc_ops);
  843. BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
  844. spin_lock(&nfs_client_lock);
  845. list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
  846. list_add_tail(&server->master_link, &nfs_volume_list);
  847. spin_unlock(&nfs_client_lock);
  848. server->mount_time = jiffies;
  849. dprintk("<-- nfs4_create_server() = %p\n", server);
  850. return server;
  851. error:
  852. nfs_free_server(server);
  853. dprintk("<-- nfs4_create_server() = error %d\n", error);
  854. return ERR_PTR(error);
  855. }
  856. /*
  857. * Create an NFS4 referral server record
  858. */
  859. struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
  860. struct nfs_fh *fh)
  861. {
  862. struct nfs_client *parent_client;
  863. struct nfs_server *server, *parent_server;
  864. struct nfs_fattr fattr;
  865. int error;
  866. dprintk("--> nfs4_create_referral_server()\n");
  867. server = nfs_alloc_server();
  868. if (!server)
  869. return ERR_PTR(-ENOMEM);
  870. parent_server = NFS_SB(data->sb);
  871. parent_client = parent_server->nfs_client;
  872. /* Get a client representation.
  873. * Note: NFSv4 always uses TCP, */
  874. error = nfs4_set_client(server, data->hostname, data->addr,
  875. data->authflavor,
  876. parent_server->client->cl_xprt->prot,
  877. parent_client->retrans_timeo,
  878. parent_client->retrans_count);
  879. if (error < 0)
  880. goto error;
  881. /* Initialise the client representation from the parent server */
  882. nfs_server_copy_userdata(server, parent_server);
  883. server->caps |= NFS_CAP_ATOMIC_OPEN;
  884. error = nfs_init_server_rpcclient(server, data->authflavor);
  885. if (error < 0)
  886. goto error;
  887. BUG_ON(!server->nfs_client);
  888. BUG_ON(!server->nfs_client->rpc_ops);
  889. BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
  890. /* probe the filesystem info for this server filesystem */
  891. error = nfs_probe_fsinfo(server, fh, &fattr);
  892. if (error < 0)
  893. goto error;
  894. dprintk("Referral FSID: %llx:%llx\n",
  895. (unsigned long long) server->fsid.major,
  896. (unsigned long long) server->fsid.minor);
  897. spin_lock(&nfs_client_lock);
  898. list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
  899. list_add_tail(&server->master_link, &nfs_volume_list);
  900. spin_unlock(&nfs_client_lock);
  901. server->mount_time = jiffies;
  902. dprintk("<-- nfs_create_referral_server() = %p\n", server);
  903. return server;
  904. error:
  905. nfs_free_server(server);
  906. dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
  907. return ERR_PTR(error);
  908. }
  909. #endif /* CONFIG_NFS_V4 */
  910. /*
  911. * Clone an NFS2, NFS3 or NFS4 server record
  912. */
  913. struct nfs_server *nfs_clone_server(struct nfs_server *source,
  914. struct nfs_fh *fh,
  915. struct nfs_fattr *fattr)
  916. {
  917. struct nfs_server *server;
  918. struct nfs_fattr fattr_fsinfo;
  919. int error;
  920. dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
  921. (unsigned long long) fattr->fsid.major,
  922. (unsigned long long) fattr->fsid.minor);
  923. server = nfs_alloc_server();
  924. if (!server)
  925. return ERR_PTR(-ENOMEM);
  926. /* Copy data from the source */
  927. server->nfs_client = source->nfs_client;
  928. atomic_inc(&server->nfs_client->cl_count);
  929. nfs_server_copy_userdata(server, source);
  930. server->fsid = fattr->fsid;
  931. error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor);
  932. if (error < 0)
  933. goto out_free_server;
  934. if (!IS_ERR(source->client_acl))
  935. nfs_init_server_aclclient(server);
  936. /* probe the filesystem info for this server filesystem */
  937. error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
  938. if (error < 0)
  939. goto out_free_server;
  940. dprintk("Cloned FSID: %llx:%llx\n",
  941. (unsigned long long) server->fsid.major,
  942. (unsigned long long) server->fsid.minor);
  943. error = nfs_start_lockd(server);
  944. if (error < 0)
  945. goto out_free_server;
  946. spin_lock(&nfs_client_lock);
  947. list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
  948. list_add_tail(&server->master_link, &nfs_volume_list);
  949. spin_unlock(&nfs_client_lock);
  950. server->mount_time = jiffies;
  951. dprintk("<-- nfs_clone_server() = %p\n", server);
  952. return server;
  953. out_free_server:
  954. nfs_free_server(server);
  955. dprintk("<-- nfs_clone_server() = error %d\n", error);
  956. return ERR_PTR(error);
  957. }
  958. #ifdef CONFIG_PROC_FS
  959. static struct proc_dir_entry *proc_fs_nfs;
  960. static int nfs_server_list_open(struct inode *inode, struct file *file);
  961. static void *nfs_server_list_start(struct seq_file *p, loff_t *pos);
  962. static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos);
  963. static void nfs_server_list_stop(struct seq_file *p, void *v);
  964. static int nfs_server_list_show(struct seq_file *m, void *v);
  965. static struct seq_operations nfs_server_list_ops = {
  966. .start = nfs_server_list_start,
  967. .next = nfs_server_list_next,
  968. .stop = nfs_server_list_stop,
  969. .show = nfs_server_list_show,
  970. };
  971. static struct file_operations nfs_server_list_fops = {
  972. .open = nfs_server_list_open,
  973. .read = seq_read,
  974. .llseek = seq_lseek,
  975. .release = seq_release,
  976. };
  977. static int nfs_volume_list_open(struct inode *inode, struct file *file);
  978. static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos);
  979. static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos);
  980. static void nfs_volume_list_stop(struct seq_file *p, void *v);
  981. static int nfs_volume_list_show(struct seq_file *m, void *v);
  982. static struct seq_operations nfs_volume_list_ops = {
  983. .start = nfs_volume_list_start,
  984. .next = nfs_volume_list_next,
  985. .stop = nfs_volume_list_stop,
  986. .show = nfs_volume_list_show,
  987. };
  988. static struct file_operations nfs_volume_list_fops = {
  989. .open = nfs_volume_list_open,
  990. .read = seq_read,
  991. .llseek = seq_lseek,
  992. .release = seq_release,
  993. };
  994. /*
  995. * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which
  996. * we're dealing
  997. */
  998. static int nfs_server_list_open(struct inode *inode, struct file *file)
  999. {
  1000. struct seq_file *m;
  1001. int ret;
  1002. ret = seq_open(file, &nfs_server_list_ops);
  1003. if (ret < 0)
  1004. return ret;
  1005. m = file->private_data;
  1006. m->private = PDE(inode)->data;
  1007. return 0;
  1008. }
  1009. /*
  1010. * set up the iterator to start reading from the server list and return the first item
  1011. */
  1012. static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
  1013. {
  1014. struct list_head *_p;
  1015. loff_t pos = *_pos;
  1016. /* lock the list against modification */
  1017. spin_lock(&nfs_client_lock);
  1018. /* allow for the header line */
  1019. if (!pos)
  1020. return SEQ_START_TOKEN;
  1021. pos--;
  1022. /* find the n'th element in the list */
  1023. list_for_each(_p, &nfs_client_list)
  1024. if (!pos--)
  1025. break;
  1026. return _p != &nfs_client_list ? _p : NULL;
  1027. }
  1028. /*
  1029. * move to next server
  1030. */
  1031. static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
  1032. {
  1033. struct list_head *_p;
  1034. (*pos)++;
  1035. _p = v;
  1036. _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next;
  1037. return _p != &nfs_client_list ? _p : NULL;
  1038. }
  1039. /*
  1040. * clean up after reading from the transports list
  1041. */
  1042. static void nfs_server_list_stop(struct seq_file *p, void *v)
  1043. {
  1044. spin_unlock(&nfs_client_lock);
  1045. }
  1046. /*
  1047. * display a header line followed by a load of call lines
  1048. */
  1049. static int nfs_server_list_show(struct seq_file *m, void *v)
  1050. {
  1051. struct nfs_client *clp;
  1052. /* display header on line 1 */
  1053. if (v == SEQ_START_TOKEN) {
  1054. seq_puts(m, "NV SERVER PORT USE HOSTNAME\n");
  1055. return 0;
  1056. }
  1057. /* display one transport per line on subsequent lines */
  1058. clp = list_entry(v, struct nfs_client, cl_share_link);
  1059. seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n",
  1060. clp->cl_nfsversion,
  1061. NIPQUAD(clp->cl_addr.sin_addr),
  1062. ntohs(clp->cl_addr.sin_port),
  1063. atomic_read(&clp->cl_count),
  1064. clp->cl_hostname);
  1065. return 0;
  1066. }
  1067. /*
  1068. * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes
  1069. */
  1070. static int nfs_volume_list_open(struct inode *inode, struct file *file)
  1071. {
  1072. struct seq_file *m;
  1073. int ret;
  1074. ret = seq_open(file, &nfs_volume_list_ops);
  1075. if (ret < 0)
  1076. return ret;
  1077. m = file->private_data;
  1078. m->private = PDE(inode)->data;
  1079. return 0;
  1080. }
  1081. /*
  1082. * set up the iterator to start reading from the volume list and return the first item
  1083. */
  1084. static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
  1085. {
  1086. struct list_head *_p;
  1087. loff_t pos = *_pos;
  1088. /* lock the list against modification */
  1089. spin_lock(&nfs_client_lock);
  1090. /* allow for the header line */
  1091. if (!pos)
  1092. return SEQ_START_TOKEN;
  1093. pos--;
  1094. /* find the n'th element in the list */
  1095. list_for_each(_p, &nfs_volume_list)
  1096. if (!pos--)
  1097. break;
  1098. return _p != &nfs_volume_list ? _p : NULL;
  1099. }
  1100. /*
  1101. * move to next volume
  1102. */
  1103. static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
  1104. {
  1105. struct list_head *_p;
  1106. (*pos)++;
  1107. _p = v;
  1108. _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next;
  1109. return _p != &nfs_volume_list ? _p : NULL;
  1110. }
  1111. /*
  1112. * clean up after reading from the transports list
  1113. */
  1114. static void nfs_volume_list_stop(struct seq_file *p, void *v)
  1115. {
  1116. spin_unlock(&nfs_client_lock);
  1117. }
  1118. /*
  1119. * display a header line followed by a load of call lines
  1120. */
  1121. static int nfs_volume_list_show(struct seq_file *m, void *v)
  1122. {
  1123. struct nfs_server *server;
  1124. struct nfs_client *clp;
  1125. char dev[8], fsid[17];
  1126. /* display header on line 1 */
  1127. if (v == SEQ_START_TOKEN) {
  1128. seq_puts(m, "NV SERVER PORT DEV FSID\n");
  1129. return 0;
  1130. }
  1131. /* display one transport per line on subsequent lines */
  1132. server = list_entry(v, struct nfs_server, master_link);
  1133. clp = server->nfs_client;
  1134. snprintf(dev, 8, "%u:%u",
  1135. MAJOR(server->s_dev), MINOR(server->s_dev));
  1136. snprintf(fsid, 17, "%llx:%llx",
  1137. (unsigned long long) server->fsid.major,
  1138. (unsigned long long) server->fsid.minor);
  1139. seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n",
  1140. clp->cl_nfsversion,
  1141. NIPQUAD(clp->cl_addr.sin_addr),
  1142. ntohs(clp->cl_addr.sin_port),
  1143. dev,
  1144. fsid);
  1145. return 0;
  1146. }
  1147. /*
  1148. * initialise the /proc/fs/nfsfs/ directory
  1149. */
  1150. int __init nfs_fs_proc_init(void)
  1151. {
  1152. struct proc_dir_entry *p;
  1153. proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs);
  1154. if (!proc_fs_nfs)
  1155. goto error_0;
  1156. proc_fs_nfs->owner = THIS_MODULE;
  1157. /* a file of servers with which we're dealing */
  1158. p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs);
  1159. if (!p)
  1160. goto error_1;
  1161. p->proc_fops = &nfs_server_list_fops;
  1162. p->owner = THIS_MODULE;
  1163. /* a file of volumes that we have mounted */
  1164. p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs);
  1165. if (!p)
  1166. goto error_2;
  1167. p->proc_fops = &nfs_volume_list_fops;
  1168. p->owner = THIS_MODULE;
  1169. return 0;
  1170. error_2:
  1171. remove_proc_entry("servers", proc_fs_nfs);
  1172. error_1:
  1173. remove_proc_entry("nfsfs", proc_root_fs);
  1174. error_0:
  1175. return -ENOMEM;
  1176. }
  1177. /*
  1178. * clean up the /proc/fs/nfsfs/ directory
  1179. */
  1180. void nfs_fs_proc_exit(void)
  1181. {
  1182. remove_proc_entry("volumes", proc_fs_nfs);
  1183. remove_proc_entry("servers", proc_fs_nfs);
  1184. remove_proc_entry("nfsfs", proc_root_fs);
  1185. }
  1186. #endif /* CONFIG_PROC_FS */