client.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  1. /*
  2. * net/9p/clnt.c
  3. *
  4. * 9P Client
  5. *
  6. * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
  7. * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to:
  20. * Free Software Foundation
  21. * 51 Franklin Street, Fifth Floor
  22. * Boston, MA 02111-1301 USA
  23. *
  24. */
  25. #include <linux/module.h>
  26. #include <linux/errno.h>
  27. #include <linux/fs.h>
  28. #include <linux/poll.h>
  29. #include <linux/idr.h>
  30. #include <linux/mutex.h>
  31. #include <linux/sched.h>
  32. #include <linux/uaccess.h>
  33. #include <net/9p/9p.h>
  34. #include <linux/parser.h>
  35. #include <net/9p/client.h>
  36. #include <net/9p/transport.h>
  37. /*
  38. * Client Option Parsing (code inspired by NFS code)
  39. * - a little lazy - parse all client options
  40. */
  41. enum {
  42. Opt_msize,
  43. Opt_trans,
  44. Opt_legacy,
  45. Opt_err,
  46. };
  47. static const match_table_t tokens = {
  48. {Opt_msize, "msize=%u"},
  49. {Opt_legacy, "noextend"},
  50. {Opt_trans, "trans=%s"},
  51. {Opt_err, NULL},
  52. };
  53. static int
  54. p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc);
  55. /**
  56. * v9fs_parse_options - parse mount options into session structure
  57. * @options: options string passed from mount
  58. * @v9ses: existing v9fs session information
  59. *
  60. * Return 0 upon success, -ERRNO upon failure
  61. */
  62. static int parse_opts(char *opts, struct p9_client *clnt)
  63. {
  64. char *options;
  65. char *p;
  66. substring_t args[MAX_OPT_ARGS];
  67. int option;
  68. int ret = 0;
  69. clnt->dotu = 1;
  70. clnt->msize = 8192;
  71. if (!opts)
  72. return 0;
  73. options = kstrdup(opts, GFP_KERNEL);
  74. if (!options) {
  75. P9_DPRINTK(P9_DEBUG_ERROR,
  76. "failed to allocate copy of option string\n");
  77. return -ENOMEM;
  78. }
  79. while ((p = strsep(&options, ",")) != NULL) {
  80. int token;
  81. if (!*p)
  82. continue;
  83. token = match_token(p, tokens, args);
  84. if (token < Opt_trans) {
  85. int r = match_int(&args[0], &option);
  86. if (r < 0) {
  87. P9_DPRINTK(P9_DEBUG_ERROR,
  88. "integer field, but no integer?\n");
  89. ret = r;
  90. continue;
  91. }
  92. }
  93. switch (token) {
  94. case Opt_msize:
  95. clnt->msize = option;
  96. break;
  97. case Opt_trans:
  98. clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
  99. break;
  100. case Opt_legacy:
  101. clnt->dotu = 0;
  102. break;
  103. default:
  104. continue;
  105. }
  106. }
  107. if (!clnt->trans_mod)
  108. clnt->trans_mod = v9fs_get_default_trans();
  109. kfree(options);
  110. return ret;
  111. }
  112. /**
  113. * p9_tag_alloc - lookup/allocate a request by tag
  114. * @c: client session to lookup tag within
  115. * @tag: numeric id for transaction
  116. *
  117. * this is a simple array lookup, but will grow the
  118. * request_slots as necessary to accomodate transaction
  119. * ids which did not previously have a slot.
  120. *
  121. * this code relies on the client spinlock to manage locks, its
  122. * possible we should switch to something else, but I'd rather
  123. * stick with something low-overhead for the common case.
  124. *
  125. */
  126. struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
  127. {
  128. unsigned long flags;
  129. int row, col;
  130. /* This looks up the original request by tag so we know which
  131. * buffer to read the data into */
  132. tag++;
  133. if (tag >= c->max_tag) {
  134. spin_lock_irqsave(&c->lock, flags);
  135. /* check again since original check was outside of lock */
  136. while (tag >= c->max_tag) {
  137. row = (tag / P9_ROW_MAXTAG);
  138. c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
  139. sizeof(struct p9_req_t), GFP_ATOMIC);
  140. if (!c->reqs[row]) {
  141. printk(KERN_ERR "Couldn't grow tag array\n");
  142. BUG();
  143. }
  144. for (col = 0; col < P9_ROW_MAXTAG; col++) {
  145. c->reqs[row][col].status = REQ_STATUS_IDLE;
  146. c->reqs[row][col].flush_tag = P9_NOTAG;
  147. c->reqs[row][col].wq = kmalloc(
  148. sizeof(wait_queue_head_t), GFP_ATOMIC);
  149. if (!c->reqs[row][col].wq) {
  150. printk(KERN_ERR
  151. "Couldn't grow tag array\n");
  152. BUG();
  153. }
  154. init_waitqueue_head(c->reqs[row][col].wq);
  155. }
  156. c->max_tag += P9_ROW_MAXTAG;
  157. }
  158. spin_unlock_irqrestore(&c->lock, flags);
  159. }
  160. row = tag / P9_ROW_MAXTAG;
  161. col = tag % P9_ROW_MAXTAG;
  162. c->reqs[row][col].status = REQ_STATUS_ALLOC;
  163. c->reqs[row][col].flush_tag = P9_NOTAG;
  164. return &c->reqs[row][col];
  165. }
  166. EXPORT_SYMBOL(p9_tag_alloc);
  167. /**
  168. * p9_tag_lookup - lookup a request by tag
  169. * @c: client session to lookup tag within
  170. * @tag: numeric id for transaction
  171. *
  172. */
  173. struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
  174. {
  175. int row, col;
  176. /* This looks up the original request by tag so we know which
  177. * buffer to read the data into */
  178. tag++;
  179. BUG_ON(tag >= c->max_tag);
  180. row = tag / P9_ROW_MAXTAG;
  181. col = tag % P9_ROW_MAXTAG;
  182. return &c->reqs[row][col];
  183. }
  184. EXPORT_SYMBOL(p9_tag_lookup);
  185. /**
  186. * p9_tag_init - setup tags structure and contents
  187. * @tags: tags structure from the client struct
  188. *
  189. * This initializes the tags structure for each client instance.
  190. *
  191. */
  192. static int p9_tag_init(struct p9_client *c)
  193. {
  194. int err = 0;
  195. c->tagpool = p9_idpool_create();
  196. if (IS_ERR(c->tagpool)) {
  197. err = PTR_ERR(c->tagpool);
  198. c->tagpool = NULL;
  199. goto error;
  200. }
  201. p9_idpool_get(c->tagpool); /* reserve tag 0 */
  202. c->max_tag = 0;
  203. error:
  204. return err;
  205. }
  206. /**
  207. * p9_tag_cleanup - cleans up tags structure and reclaims resources
  208. * @tags: tags structure from the client struct
  209. *
  210. * This frees resources associated with the tags structure
  211. *
  212. */
  213. static void p9_tag_cleanup(struct p9_client *c)
  214. {
  215. int row, col;
  216. /* check to insure all requests are idle */
  217. for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
  218. for (col = 0; col < P9_ROW_MAXTAG; col++) {
  219. if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
  220. P9_DPRINTK(P9_DEBUG_MUX,
  221. "Attempting to cleanup non-free tag %d,%d\n",
  222. row, col);
  223. /* TODO: delay execution of cleanup */
  224. return;
  225. }
  226. }
  227. }
  228. if (c->tagpool)
  229. p9_idpool_destroy(c->tagpool);
  230. /* free requests associated with tags */
  231. for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
  232. for (col = 0; col < P9_ROW_MAXTAG; col++)
  233. kfree(c->reqs[row][col].wq);
  234. kfree(c->reqs[row]);
  235. }
  236. c->max_tag = 0;
  237. }
  238. /**
  239. * p9_client_flush - flush (cancel) a request
  240. * c: client state
  241. * req: request to cancel
  242. *
  243. * This sents a flush for a particular requests and links
  244. * the flush request to the original request. The current
  245. * code only supports a single flush request although the protocol
  246. * allows for multiple flush requests to be sent for a single request.
  247. *
  248. */
  249. static int p9_client_flush(struct p9_client *c, struct p9_req_t *req)
  250. {
  251. struct p9_fcall *tc, *rc = NULL;
  252. int err;
  253. P9_DPRINTK(P9_DEBUG_9P, "client %p tag %d\n", c, req->tc->tag);
  254. tc = p9_create_tflush(req->tc->tag);
  255. if (IS_ERR(tc))
  256. return PTR_ERR(tc);
  257. err = p9_client_rpc(c, tc, &rc);
  258. /* we don't free anything here because RPC isn't complete */
  259. return err;
  260. }
  261. /**
  262. * p9_free_req - free a request and clean-up as necessary
  263. * c: client state
  264. * r: request to release
  265. *
  266. */
  267. void p9_free_req(struct p9_client *c, struct p9_req_t *r)
  268. {
  269. r->flush_tag = P9_NOTAG;
  270. r->status = REQ_STATUS_IDLE;
  271. if (r->tc->tag != P9_NOTAG && p9_idpool_check(r->tc->tag, c->tagpool))
  272. p9_idpool_put(r->tc->tag, c->tagpool);
  273. /* if this was a flush request we have to free response fcall */
  274. if (r->tc->id == P9_TFLUSH) {
  275. kfree(r->tc);
  276. kfree(r->rc);
  277. }
  278. }
  279. /**
  280. * p9_client_cb - call back from transport to client
  281. * c: client state
  282. * req: request received
  283. *
  284. */
  285. void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
  286. {
  287. struct p9_req_t *other_req;
  288. unsigned long flags;
  289. P9_DPRINTK(P9_DEBUG_MUX, ": %d\n", req->tc->tag);
  290. if (req->status == REQ_STATUS_ERROR)
  291. wake_up(req->wq);
  292. if (req->tc->id == P9_TFLUSH) { /* flush receive path */
  293. P9_DPRINTK(P9_DEBUG_MUX, "flush: %d\n", req->tc->tag);
  294. spin_lock_irqsave(&c->lock, flags);
  295. other_req = p9_tag_lookup(c, req->tc->params.tflush.oldtag);
  296. if (other_req->flush_tag != req->tc->tag) /* stale flush */
  297. spin_unlock_irqrestore(&c->lock, flags);
  298. else {
  299. BUG_ON(other_req->status != REQ_STATUS_FLSH);
  300. other_req->status = REQ_STATUS_FLSHD;
  301. spin_unlock_irqrestore(&c->lock, flags);
  302. wake_up(other_req->wq);
  303. }
  304. p9_free_req(c, req);
  305. } else { /* normal receive path */
  306. P9_DPRINTK(P9_DEBUG_MUX, "normal: %d\n", req->tc->tag);
  307. spin_lock_irqsave(&c->lock, flags);
  308. if (req->status != REQ_STATUS_FLSHD)
  309. req->status = REQ_STATUS_RCVD;
  310. req->flush_tag = P9_NOTAG;
  311. spin_unlock_irqrestore(&c->lock, flags);
  312. wake_up(req->wq);
  313. P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
  314. }
  315. }
  316. EXPORT_SYMBOL(p9_client_cb);
  317. /**
  318. * p9_client_rpc - issue a request and wait for a response
  319. * @c: client session
  320. * @tc: &p9_fcall request to transmit
  321. * @rc: &p9_fcall to put reponse into
  322. *
  323. * Returns 0 on success, error code on failure
  324. */
  325. static int
  326. p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
  327. {
  328. int tag, err, size;
  329. char *rdata;
  330. struct p9_req_t *req;
  331. unsigned long flags;
  332. int sigpending;
  333. int flushed = 0;
  334. P9_DPRINTK(P9_DEBUG_9P, "client %p tc %p rc %p\n", c, tc, rc);
  335. if (c->status != Connected)
  336. return -EIO;
  337. if (signal_pending(current)) {
  338. sigpending = 1;
  339. clear_thread_flag(TIF_SIGPENDING);
  340. } else
  341. sigpending = 0;
  342. tag = P9_NOTAG;
  343. if (tc->id != P9_TVERSION) {
  344. tag = p9_idpool_get(c->tagpool);
  345. if (tag < 0)
  346. return -ENOMEM;
  347. }
  348. req = p9_tag_alloc(c, tag);
  349. /* if this is a flush request, backlink flush request now to
  350. * avoid race conditions later. */
  351. if (tc->id == P9_TFLUSH) {
  352. struct p9_req_t *other_req =
  353. p9_tag_lookup(c, tc->params.tflush.oldtag);
  354. if (other_req->status == REQ_STATUS_FLSH)
  355. other_req->flush_tag = tag;
  356. }
  357. p9_set_tag(tc, tag);
  358. /*
  359. * if client passed in a pre-allocated response fcall struct
  360. * then we just use that, otherwise we allocate one.
  361. */
  362. if (rc == NULL)
  363. req->rc = NULL;
  364. else
  365. req->rc = *rc;
  366. if (req->rc == NULL) {
  367. req->rc = kmalloc(sizeof(struct p9_fcall) + c->msize,
  368. GFP_KERNEL);
  369. if (!req->rc) {
  370. err = -ENOMEM;
  371. p9_idpool_put(tag, c->tagpool);
  372. p9_free_req(c, req);
  373. goto reterr;
  374. }
  375. *rc = req->rc;
  376. }
  377. rdata = (char *)req->rc+sizeof(struct p9_fcall);
  378. req->tc = tc;
  379. P9_DPRINTK(P9_DEBUG_9P, "request: tc: %p rc: %p\n", req->tc, req->rc);
  380. err = c->trans_mod->request(c, req);
  381. if (err < 0) {
  382. c->status = Disconnected;
  383. goto reterr;
  384. }
  385. /* if it was a flush we just transmitted, return our tag */
  386. if (tc->id == P9_TFLUSH)
  387. return 0;
  388. again:
  389. P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d\n", req->wq, tag);
  390. err = wait_event_interruptible(*req->wq,
  391. req->status >= REQ_STATUS_RCVD);
  392. P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d returned %d (flushed=%d)\n",
  393. req->wq, tag, err, flushed);
  394. if (req->status == REQ_STATUS_ERROR) {
  395. P9_DPRINTK(P9_DEBUG_9P, "req_status error %d\n", req->t_err);
  396. err = req->t_err;
  397. } else if (err == -ERESTARTSYS && flushed) {
  398. P9_DPRINTK(P9_DEBUG_9P, "flushed - going again\n");
  399. goto again;
  400. } else if (req->status == REQ_STATUS_FLSHD) {
  401. P9_DPRINTK(P9_DEBUG_9P, "flushed - erestartsys\n");
  402. err = -ERESTARTSYS;
  403. }
  404. if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) {
  405. P9_DPRINTK(P9_DEBUG_9P, "flushing\n");
  406. spin_lock_irqsave(&c->lock, flags);
  407. if (req->status == REQ_STATUS_SENT)
  408. req->status = REQ_STATUS_FLSH;
  409. spin_unlock_irqrestore(&c->lock, flags);
  410. sigpending = 1;
  411. flushed = 1;
  412. clear_thread_flag(TIF_SIGPENDING);
  413. if (c->trans_mod->cancel(c, req)) {
  414. err = p9_client_flush(c, req);
  415. if (err == 0)
  416. goto again;
  417. }
  418. }
  419. if (sigpending) {
  420. spin_lock_irqsave(&current->sighand->siglock, flags);
  421. recalc_sigpending();
  422. spin_unlock_irqrestore(&current->sighand->siglock, flags);
  423. }
  424. if (err < 0)
  425. goto reterr;
  426. size = le32_to_cpu(*(__le32 *) rdata);
  427. err = p9_deserialize_fcall(rdata, size, req->rc, c->dotu);
  428. if (err < 0) {
  429. P9_DPRINTK(P9_DEBUG_9P,
  430. "9p debug: client rpc deserialize returned %d\n", err);
  431. goto reterr;
  432. }
  433. if (req->rc->id == P9_RERROR) {
  434. int ecode = req->rc->params.rerror.errno;
  435. struct p9_str *ename = &req->rc->params.rerror.error;
  436. P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
  437. ename->str);
  438. if (c->dotu)
  439. err = -ecode;
  440. if (!err) {
  441. err = p9_errstr2errno(ename->str, ename->len);
  442. /* string match failed */
  443. if (!err) {
  444. PRINT_FCALL_ERROR("unknown error", req->rc);
  445. err = -ESERVERFAULT;
  446. }
  447. }
  448. } else
  449. err = 0;
  450. reterr:
  451. p9_free_req(c, req);
  452. P9_DPRINTK(P9_DEBUG_9P, "returning %d\n", err);
  453. return err;
  454. }
  455. static struct p9_fid *p9_fid_create(struct p9_client *clnt)
  456. {
  457. int err;
  458. struct p9_fid *fid;
  459. P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
  460. fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
  461. if (!fid)
  462. return ERR_PTR(-ENOMEM);
  463. fid->fid = p9_idpool_get(clnt->fidpool);
  464. if (fid->fid < 0) {
  465. err = -ENOSPC;
  466. goto error;
  467. }
  468. memset(&fid->qid, 0, sizeof(struct p9_qid));
  469. fid->mode = -1;
  470. fid->rdir_fpos = 0;
  471. fid->uid = current->fsuid;
  472. fid->clnt = clnt;
  473. fid->aux = NULL;
  474. spin_lock(&clnt->lock);
  475. list_add(&fid->flist, &clnt->fidlist);
  476. spin_unlock(&clnt->lock);
  477. return fid;
  478. error:
  479. kfree(fid);
  480. return ERR_PTR(err);
  481. }
  482. static void p9_fid_destroy(struct p9_fid *fid)
  483. {
  484. struct p9_client *clnt;
  485. P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
  486. clnt = fid->clnt;
  487. p9_idpool_put(fid->fid, clnt->fidpool);
  488. spin_lock(&clnt->lock);
  489. list_del(&fid->flist);
  490. spin_unlock(&clnt->lock);
  491. kfree(fid);
  492. }
  493. static int p9_client_version(struct p9_client *clnt)
  494. {
  495. int err = 0;
  496. struct p9_fcall *tc, *rc;
  497. struct p9_str *version;
  498. P9_DPRINTK(P9_DEBUG_9P, "%p\n", clnt);
  499. err = 0;
  500. tc = NULL;
  501. rc = NULL;
  502. tc = p9_create_tversion(clnt->msize,
  503. clnt->dotu ? "9P2000.u" : "9P2000");
  504. if (IS_ERR(tc)) {
  505. err = PTR_ERR(tc);
  506. tc = NULL;
  507. goto error;
  508. }
  509. err = p9_client_rpc(clnt, tc, &rc);
  510. if (err)
  511. goto error;
  512. version = &rc->params.rversion.version;
  513. if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8))
  514. clnt->dotu = 1;
  515. else if (version->len == 6 && !memcmp(version->str, "9P2000", 6))
  516. clnt->dotu = 0;
  517. else {
  518. err = -EREMOTEIO;
  519. goto error;
  520. }
  521. if (rc->params.rversion.msize < clnt->msize)
  522. clnt->msize = rc->params.rversion.msize;
  523. error:
  524. kfree(tc);
  525. kfree(rc);
  526. return err;
  527. }
  528. EXPORT_SYMBOL(p9_client_auth);
  529. struct p9_client *p9_client_create(const char *dev_name, char *options)
  530. {
  531. int err;
  532. struct p9_client *clnt;
  533. err = 0;
  534. clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
  535. if (!clnt)
  536. return ERR_PTR(-ENOMEM);
  537. clnt->trans_mod = NULL;
  538. clnt->trans = NULL;
  539. spin_lock_init(&clnt->lock);
  540. INIT_LIST_HEAD(&clnt->fidlist);
  541. clnt->fidpool = p9_idpool_create();
  542. if (IS_ERR(clnt->fidpool)) {
  543. err = PTR_ERR(clnt->fidpool);
  544. clnt->fidpool = NULL;
  545. goto error;
  546. }
  547. p9_tag_init(clnt);
  548. err = parse_opts(options, clnt);
  549. if (err < 0)
  550. goto error;
  551. if (clnt->trans_mod == NULL) {
  552. err = -EPROTONOSUPPORT;
  553. P9_DPRINTK(P9_DEBUG_ERROR,
  554. "No transport defined or default transport\n");
  555. goto error;
  556. }
  557. P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
  558. clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
  559. err = clnt->trans_mod->create(clnt, dev_name, options);
  560. if (err)
  561. goto error;
  562. if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
  563. clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
  564. err = p9_client_version(clnt);
  565. if (err)
  566. goto error;
  567. return clnt;
  568. error:
  569. p9_client_destroy(clnt);
  570. return ERR_PTR(err);
  571. }
  572. EXPORT_SYMBOL(p9_client_create);
  573. void p9_client_destroy(struct p9_client *clnt)
  574. {
  575. struct p9_fid *fid, *fidptr;
  576. P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
  577. if (clnt->trans_mod)
  578. clnt->trans_mod->close(clnt);
  579. v9fs_put_trans(clnt->trans_mod);
  580. list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
  581. p9_fid_destroy(fid);
  582. if (clnt->fidpool)
  583. p9_idpool_destroy(clnt->fidpool);
  584. p9_tag_cleanup(clnt);
  585. kfree(clnt);
  586. }
  587. EXPORT_SYMBOL(p9_client_destroy);
  588. void p9_client_disconnect(struct p9_client *clnt)
  589. {
  590. P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
  591. clnt->status = Disconnected;
  592. }
  593. EXPORT_SYMBOL(p9_client_disconnect);
  594. struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
  595. char *uname, u32 n_uname, char *aname)
  596. {
  597. int err;
  598. struct p9_fcall *tc, *rc;
  599. struct p9_fid *fid;
  600. P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n",
  601. clnt, afid?afid->fid:-1, uname, aname);
  602. err = 0;
  603. tc = NULL;
  604. rc = NULL;
  605. fid = p9_fid_create(clnt);
  606. if (IS_ERR(fid)) {
  607. err = PTR_ERR(fid);
  608. fid = NULL;
  609. goto error;
  610. }
  611. tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname,
  612. n_uname, clnt->dotu);
  613. if (IS_ERR(tc)) {
  614. err = PTR_ERR(tc);
  615. tc = NULL;
  616. goto error;
  617. }
  618. err = p9_client_rpc(clnt, tc, &rc);
  619. if (err)
  620. goto error;
  621. memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid));
  622. kfree(tc);
  623. kfree(rc);
  624. return fid;
  625. error:
  626. kfree(tc);
  627. kfree(rc);
  628. if (fid)
  629. p9_fid_destroy(fid);
  630. return ERR_PTR(err);
  631. }
  632. EXPORT_SYMBOL(p9_client_attach);
  633. struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
  634. u32 n_uname, char *aname)
  635. {
  636. int err;
  637. struct p9_fcall *tc, *rc;
  638. struct p9_fid *fid;
  639. P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname,
  640. aname);
  641. err = 0;
  642. tc = NULL;
  643. rc = NULL;
  644. fid = p9_fid_create(clnt);
  645. if (IS_ERR(fid)) {
  646. err = PTR_ERR(fid);
  647. fid = NULL;
  648. goto error;
  649. }
  650. tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu);
  651. if (IS_ERR(tc)) {
  652. err = PTR_ERR(tc);
  653. tc = NULL;
  654. goto error;
  655. }
  656. err = p9_client_rpc(clnt, tc, &rc);
  657. if (err)
  658. goto error;
  659. memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid));
  660. kfree(tc);
  661. kfree(rc);
  662. return fid;
  663. error:
  664. kfree(tc);
  665. kfree(rc);
  666. if (fid)
  667. p9_fid_destroy(fid);
  668. return ERR_PTR(err);
  669. }
  670. EXPORT_SYMBOL(p9_client_auth);
  671. struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
  672. int clone)
  673. {
  674. int err;
  675. struct p9_fcall *tc, *rc;
  676. struct p9_client *clnt;
  677. struct p9_fid *fid;
  678. P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
  679. oldfid->fid, nwname, wnames?wnames[0]:NULL);
  680. err = 0;
  681. tc = NULL;
  682. rc = NULL;
  683. clnt = oldfid->clnt;
  684. if (clone) {
  685. fid = p9_fid_create(clnt);
  686. if (IS_ERR(fid)) {
  687. err = PTR_ERR(fid);
  688. fid = NULL;
  689. goto error;
  690. }
  691. fid->uid = oldfid->uid;
  692. } else
  693. fid = oldfid;
  694. tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames);
  695. if (IS_ERR(tc)) {
  696. err = PTR_ERR(tc);
  697. tc = NULL;
  698. goto error;
  699. }
  700. err = p9_client_rpc(clnt, tc, &rc);
  701. if (err) {
  702. if (rc && rc->id == P9_RWALK)
  703. goto clunk_fid;
  704. else
  705. goto error;
  706. }
  707. if (rc->params.rwalk.nwqid != nwname) {
  708. err = -ENOENT;
  709. goto clunk_fid;
  710. }
  711. if (nwname)
  712. memmove(&fid->qid,
  713. &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
  714. sizeof(struct p9_qid));
  715. else
  716. fid->qid = oldfid->qid;
  717. kfree(tc);
  718. kfree(rc);
  719. return fid;
  720. clunk_fid:
  721. kfree(tc);
  722. kfree(rc);
  723. rc = NULL;
  724. tc = p9_create_tclunk(fid->fid);
  725. if (IS_ERR(tc)) {
  726. err = PTR_ERR(tc);
  727. tc = NULL;
  728. goto error;
  729. }
  730. p9_client_rpc(clnt, tc, &rc);
  731. error:
  732. kfree(tc);
  733. kfree(rc);
  734. if (fid && (fid != oldfid))
  735. p9_fid_destroy(fid);
  736. return ERR_PTR(err);
  737. }
  738. EXPORT_SYMBOL(p9_client_walk);
  739. int p9_client_open(struct p9_fid *fid, int mode)
  740. {
  741. int err;
  742. struct p9_fcall *tc, *rc;
  743. struct p9_client *clnt;
  744. P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode);
  745. err = 0;
  746. tc = NULL;
  747. rc = NULL;
  748. clnt = fid->clnt;
  749. if (fid->mode != -1)
  750. return -EINVAL;
  751. tc = p9_create_topen(fid->fid, mode);
  752. if (IS_ERR(tc)) {
  753. err = PTR_ERR(tc);
  754. tc = NULL;
  755. goto done;
  756. }
  757. err = p9_client_rpc(clnt, tc, &rc);
  758. if (err)
  759. goto done;
  760. fid->mode = mode;
  761. fid->iounit = rc->params.ropen.iounit;
  762. done:
  763. kfree(tc);
  764. kfree(rc);
  765. return err;
  766. }
  767. EXPORT_SYMBOL(p9_client_open);
  768. int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
  769. char *extension)
  770. {
  771. int err;
  772. struct p9_fcall *tc, *rc;
  773. struct p9_client *clnt;
  774. P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid,
  775. name, perm, mode);
  776. err = 0;
  777. tc = NULL;
  778. rc = NULL;
  779. clnt = fid->clnt;
  780. if (fid->mode != -1)
  781. return -EINVAL;
  782. tc = p9_create_tcreate(fid->fid, name, perm, mode, extension,
  783. clnt->dotu);
  784. if (IS_ERR(tc)) {
  785. err = PTR_ERR(tc);
  786. tc = NULL;
  787. goto done;
  788. }
  789. err = p9_client_rpc(clnt, tc, &rc);
  790. if (err)
  791. goto done;
  792. fid->mode = mode;
  793. fid->iounit = rc->params.ropen.iounit;
  794. done:
  795. kfree(tc);
  796. kfree(rc);
  797. return err;
  798. }
  799. EXPORT_SYMBOL(p9_client_fcreate);
  800. int p9_client_clunk(struct p9_fid *fid)
  801. {
  802. int err;
  803. struct p9_fcall *tc, *rc;
  804. struct p9_client *clnt;
  805. P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
  806. err = 0;
  807. tc = NULL;
  808. rc = NULL;
  809. clnt = fid->clnt;
  810. tc = p9_create_tclunk(fid->fid);
  811. if (IS_ERR(tc)) {
  812. err = PTR_ERR(tc);
  813. tc = NULL;
  814. goto done;
  815. }
  816. err = p9_client_rpc(clnt, tc, &rc);
  817. if (err)
  818. goto done;
  819. p9_fid_destroy(fid);
  820. done:
  821. kfree(tc);
  822. kfree(rc);
  823. return err;
  824. }
  825. EXPORT_SYMBOL(p9_client_clunk);
  826. int p9_client_remove(struct p9_fid *fid)
  827. {
  828. int err;
  829. struct p9_fcall *tc, *rc;
  830. struct p9_client *clnt;
  831. P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
  832. err = 0;
  833. tc = NULL;
  834. rc = NULL;
  835. clnt = fid->clnt;
  836. tc = p9_create_tremove(fid->fid);
  837. if (IS_ERR(tc)) {
  838. err = PTR_ERR(tc);
  839. tc = NULL;
  840. goto done;
  841. }
  842. err = p9_client_rpc(clnt, tc, &rc);
  843. if (err)
  844. goto done;
  845. p9_fid_destroy(fid);
  846. done:
  847. kfree(tc);
  848. kfree(rc);
  849. return err;
  850. }
  851. EXPORT_SYMBOL(p9_client_remove);
  852. int
  853. p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
  854. u32 count)
  855. {
  856. int err, n, rsize, total;
  857. struct p9_fcall *tc, *rc;
  858. struct p9_client *clnt;
  859. P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid,
  860. (long long unsigned) offset, count);
  861. err = 0;
  862. tc = NULL;
  863. rc = NULL;
  864. clnt = fid->clnt;
  865. total = 0;
  866. rsize = fid->iounit;
  867. if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
  868. rsize = clnt->msize - P9_IOHDRSZ;
  869. do {
  870. if (count < rsize)
  871. rsize = count;
  872. tc = p9_create_tread(fid->fid, offset, rsize);
  873. if (IS_ERR(tc)) {
  874. err = PTR_ERR(tc);
  875. tc = NULL;
  876. goto error;
  877. }
  878. err = p9_client_rpc(clnt, tc, &rc);
  879. if (err)
  880. goto error;
  881. n = rc->params.rread.count;
  882. if (n > count)
  883. n = count;
  884. if (data) {
  885. memmove(data, rc->params.rread.data, n);
  886. data += n;
  887. }
  888. if (udata) {
  889. err = copy_to_user(udata, rc->params.rread.data, n);
  890. if (err) {
  891. err = -EFAULT;
  892. goto error;
  893. }
  894. udata += n;
  895. }
  896. count -= n;
  897. offset += n;
  898. total += n;
  899. kfree(tc);
  900. tc = NULL;
  901. kfree(rc);
  902. rc = NULL;
  903. } while (count > 0 && n == rsize);
  904. return total;
  905. error:
  906. kfree(tc);
  907. kfree(rc);
  908. return err;
  909. }
  910. EXPORT_SYMBOL(p9_client_read);
  911. int
  912. p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
  913. u64 offset, u32 count)
  914. {
  915. int err, n, rsize, total;
  916. struct p9_fcall *tc, *rc;
  917. struct p9_client *clnt;
  918. P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
  919. (long long unsigned) offset, count);
  920. err = 0;
  921. tc = NULL;
  922. rc = NULL;
  923. clnt = fid->clnt;
  924. total = 0;
  925. rsize = fid->iounit;
  926. if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
  927. rsize = clnt->msize - P9_IOHDRSZ;
  928. do {
  929. if (count < rsize)
  930. rsize = count;
  931. if (data)
  932. tc = p9_create_twrite(fid->fid, offset, rsize, data);
  933. else
  934. tc = p9_create_twrite_u(fid->fid, offset, rsize, udata);
  935. if (IS_ERR(tc)) {
  936. err = PTR_ERR(tc);
  937. tc = NULL;
  938. goto error;
  939. }
  940. err = p9_client_rpc(clnt, tc, &rc);
  941. if (err)
  942. goto error;
  943. n = rc->params.rread.count;
  944. count -= n;
  945. if (data)
  946. data += n;
  947. else
  948. udata += n;
  949. offset += n;
  950. total += n;
  951. kfree(tc);
  952. tc = NULL;
  953. kfree(rc);
  954. rc = NULL;
  955. } while (count > 0);
  956. return total;
  957. error:
  958. kfree(tc);
  959. kfree(rc);
  960. return err;
  961. }
  962. EXPORT_SYMBOL(p9_client_write);
  963. static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
  964. {
  965. int n;
  966. char *p;
  967. struct p9_stat *ret;
  968. n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
  969. st->muid.len;
  970. if (dotu)
  971. n += st->extension.len;
  972. ret = kmalloc(n, GFP_KERNEL);
  973. if (!ret)
  974. return ERR_PTR(-ENOMEM);
  975. memmove(ret, st, sizeof(struct p9_stat));
  976. p = ((char *) ret) + sizeof(struct p9_stat);
  977. memmove(p, st->name.str, st->name.len);
  978. ret->name.str = p;
  979. p += st->name.len;
  980. memmove(p, st->uid.str, st->uid.len);
  981. ret->uid.str = p;
  982. p += st->uid.len;
  983. memmove(p, st->gid.str, st->gid.len);
  984. ret->gid.str = p;
  985. p += st->gid.len;
  986. memmove(p, st->muid.str, st->muid.len);
  987. ret->muid.str = p;
  988. p += st->muid.len;
  989. if (dotu) {
  990. memmove(p, st->extension.str, st->extension.len);
  991. ret->extension.str = p;
  992. p += st->extension.len;
  993. }
  994. return ret;
  995. }
  996. struct p9_stat *p9_client_stat(struct p9_fid *fid)
  997. {
  998. int err;
  999. struct p9_fcall *tc, *rc;
  1000. struct p9_client *clnt;
  1001. struct p9_stat *ret;
  1002. P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
  1003. err = 0;
  1004. tc = NULL;
  1005. rc = NULL;
  1006. ret = NULL;
  1007. clnt = fid->clnt;
  1008. tc = p9_create_tstat(fid->fid);
  1009. if (IS_ERR(tc)) {
  1010. err = PTR_ERR(tc);
  1011. tc = NULL;
  1012. goto error;
  1013. }
  1014. err = p9_client_rpc(clnt, tc, &rc);
  1015. if (err)
  1016. goto error;
  1017. ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu);
  1018. if (IS_ERR(ret)) {
  1019. err = PTR_ERR(ret);
  1020. ret = NULL;
  1021. goto error;
  1022. }
  1023. kfree(tc);
  1024. kfree(rc);
  1025. return ret;
  1026. error:
  1027. kfree(tc);
  1028. kfree(rc);
  1029. kfree(ret);
  1030. return ERR_PTR(err);
  1031. }
  1032. EXPORT_SYMBOL(p9_client_stat);
  1033. int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
  1034. {
  1035. int err;
  1036. struct p9_fcall *tc, *rc;
  1037. struct p9_client *clnt;
  1038. P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
  1039. err = 0;
  1040. tc = NULL;
  1041. rc = NULL;
  1042. clnt = fid->clnt;
  1043. tc = p9_create_twstat(fid->fid, wst, clnt->dotu);
  1044. if (IS_ERR(tc)) {
  1045. err = PTR_ERR(tc);
  1046. tc = NULL;
  1047. goto done;
  1048. }
  1049. err = p9_client_rpc(clnt, tc, &rc);
  1050. done:
  1051. kfree(tc);
  1052. kfree(rc);
  1053. return err;
  1054. }
  1055. EXPORT_SYMBOL(p9_client_wstat);