6 * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
7 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
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.
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.
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
26 #include <linux/module.h>
27 #include <linux/errno.h>
29 #include <linux/poll.h>
30 #include <linux/idr.h>
31 #include <linux/mutex.h>
32 #include <linux/slab.h>
33 #include <linux/sched.h>
34 #include <linux/uaccess.h>
35 #include <net/9p/9p.h>
36 #include <linux/parser.h>
37 #include <net/9p/client.h>
38 #include <net/9p/transport.h>
42 * Client Option Parsing (code inspired by NFS code)
43 * - a little lazy - parse all client options
54 static const match_table_t tokens
= {
55 {Opt_msize
, "msize=%u"},
56 {Opt_legacy
, "noextend"},
57 {Opt_trans
, "trans=%s"},
58 {Opt_version
, "version=%s"},
62 inline int p9_is_proto_dotl(struct p9_client
*clnt
)
64 return clnt
->proto_version
== p9_proto_2000L
;
66 EXPORT_SYMBOL(p9_is_proto_dotl
);
68 inline int p9_is_proto_dotu(struct p9_client
*clnt
)
70 return clnt
->proto_version
== p9_proto_2000u
;
72 EXPORT_SYMBOL(p9_is_proto_dotu
);
74 /* Interpret mount option for protocol version */
75 static int get_protocol_version(const substring_t
*name
)
77 int version
= -EINVAL
;
79 if (!strncmp("9p2000", name
->from
, name
->to
-name
->from
)) {
80 version
= p9_proto_legacy
;
81 P9_DPRINTK(P9_DEBUG_9P
, "Protocol version: Legacy\n");
82 } else if (!strncmp("9p2000.u", name
->from
, name
->to
-name
->from
)) {
83 version
= p9_proto_2000u
;
84 P9_DPRINTK(P9_DEBUG_9P
, "Protocol version: 9P2000.u\n");
85 } else if (!strncmp("9p2000.L", name
->from
, name
->to
-name
->from
)) {
86 version
= p9_proto_2000L
;
87 P9_DPRINTK(P9_DEBUG_9P
, "Protocol version: 9P2000.L\n");
89 P9_DPRINTK(P9_DEBUG_ERROR
, "Unknown protocol version %s. ",
96 * parse_options - parse mount options into client structure
97 * @opts: options string passed from mount
98 * @clnt: existing v9fs client information
100 * Return 0 upon success, -ERRNO upon failure
103 static int parse_opts(char *opts
, struct p9_client
*clnt
)
105 char *options
, *tmp_options
;
107 substring_t args
[MAX_OPT_ARGS
];
111 clnt
->proto_version
= p9_proto_2000u
;
117 tmp_options
= kstrdup(opts
, GFP_KERNEL
);
119 P9_DPRINTK(P9_DEBUG_ERROR
,
120 "failed to allocate copy of option string\n");
123 options
= tmp_options
;
125 while ((p
= strsep(&options
, ",")) != NULL
) {
129 token
= match_token(p
, tokens
, args
);
130 if (token
< Opt_trans
) {
131 int r
= match_int(&args
[0], &option
);
133 P9_DPRINTK(P9_DEBUG_ERROR
,
134 "integer field, but no integer?\n");
141 clnt
->msize
= option
;
144 clnt
->trans_mod
= v9fs_get_trans_by_name(&args
[0]);
145 if(clnt
->trans_mod
== NULL
) {
146 P9_DPRINTK(P9_DEBUG_ERROR
,
147 "Could not find request transport: %s\n",
150 goto free_and_return
;
154 clnt
->proto_version
= p9_proto_legacy
;
157 ret
= get_protocol_version(&args
[0]);
159 goto free_and_return
;
160 clnt
->proto_version
= ret
;
173 * p9_tag_alloc - lookup/allocate a request by tag
174 * @c: client session to lookup tag within
175 * @tag: numeric id for transaction
177 * this is a simple array lookup, but will grow the
178 * request_slots as necessary to accommodate transaction
179 * ids which did not previously have a slot.
181 * this code relies on the client spinlock to manage locks, its
182 * possible we should switch to something else, but I'd rather
183 * stick with something low-overhead for the common case.
187 static struct p9_req_t
*p9_tag_alloc(struct p9_client
*c
, u16 tag
)
191 struct p9_req_t
*req
;
193 /* This looks up the original request by tag so we know which
194 * buffer to read the data into */
197 if (tag
>= c
->max_tag
) {
198 spin_lock_irqsave(&c
->lock
, flags
);
199 /* check again since original check was outside of lock */
200 while (tag
>= c
->max_tag
) {
201 row
= (tag
/ P9_ROW_MAXTAG
);
202 c
->reqs
[row
] = kcalloc(P9_ROW_MAXTAG
,
203 sizeof(struct p9_req_t
), GFP_ATOMIC
);
206 printk(KERN_ERR
"Couldn't grow tag array\n");
207 spin_unlock_irqrestore(&c
->lock
, flags
);
208 return ERR_PTR(-ENOMEM
);
210 for (col
= 0; col
< P9_ROW_MAXTAG
; col
++) {
211 c
->reqs
[row
][col
].status
= REQ_STATUS_IDLE
;
212 c
->reqs
[row
][col
].tc
= NULL
;
214 c
->max_tag
+= P9_ROW_MAXTAG
;
216 spin_unlock_irqrestore(&c
->lock
, flags
);
218 row
= tag
/ P9_ROW_MAXTAG
;
219 col
= tag
% P9_ROW_MAXTAG
;
221 req
= &c
->reqs
[row
][col
];
223 req
->wq
= kmalloc(sizeof(wait_queue_head_t
), GFP_NOFS
);
225 printk(KERN_ERR
"Couldn't grow tag array\n");
226 return ERR_PTR(-ENOMEM
);
228 init_waitqueue_head(req
->wq
);
229 if ((c
->trans_mod
->pref
& P9_TRANS_PREF_PAYLOAD_MASK
) ==
230 P9_TRANS_PREF_PAYLOAD_SEP
) {
231 int alloc_msize
= min(c
->msize
, 4096);
232 req
->tc
= kmalloc(sizeof(struct p9_fcall
)+alloc_msize
,
234 req
->tc
->capacity
= alloc_msize
;
235 req
->rc
= kmalloc(sizeof(struct p9_fcall
)+alloc_msize
,
237 req
->rc
->capacity
= alloc_msize
;
239 req
->tc
= kmalloc(sizeof(struct p9_fcall
)+c
->msize
,
241 req
->tc
->capacity
= c
->msize
;
242 req
->rc
= kmalloc(sizeof(struct p9_fcall
)+c
->msize
,
244 req
->rc
->capacity
= c
->msize
;
246 if ((!req
->tc
) || (!req
->rc
)) {
247 printk(KERN_ERR
"Couldn't grow tag array\n");
251 req
->tc
= req
->rc
= NULL
;
253 return ERR_PTR(-ENOMEM
);
255 req
->tc
->sdata
= (char *) req
->tc
+ sizeof(struct p9_fcall
);
256 req
->rc
->sdata
= (char *) req
->rc
+ sizeof(struct p9_fcall
);
259 p9pdu_reset(req
->tc
);
260 p9pdu_reset(req
->rc
);
262 req
->tc
->tag
= tag
-1;
263 req
->status
= REQ_STATUS_ALLOC
;
265 return &c
->reqs
[row
][col
];
269 * p9_tag_lookup - lookup a request by tag
270 * @c: client session to lookup tag within
271 * @tag: numeric id for transaction
275 struct p9_req_t
*p9_tag_lookup(struct p9_client
*c
, u16 tag
)
279 /* This looks up the original request by tag so we know which
280 * buffer to read the data into */
283 if(tag
>= c
->max_tag
)
286 row
= tag
/ P9_ROW_MAXTAG
;
287 col
= tag
% P9_ROW_MAXTAG
;
289 return &c
->reqs
[row
][col
];
291 EXPORT_SYMBOL(p9_tag_lookup
);
294 * p9_tag_init - setup tags structure and contents
295 * @c: v9fs client struct
297 * This initializes the tags structure for each client instance.
301 static int p9_tag_init(struct p9_client
*c
)
305 c
->tagpool
= p9_idpool_create();
306 if (IS_ERR(c
->tagpool
)) {
307 err
= PTR_ERR(c
->tagpool
);
310 err
= p9_idpool_get(c
->tagpool
); /* reserve tag 0 */
312 p9_idpool_destroy(c
->tagpool
);
321 * p9_tag_cleanup - cleans up tags structure and reclaims resources
322 * @c: v9fs client struct
324 * This frees resources associated with the tags structure
327 static void p9_tag_cleanup(struct p9_client
*c
)
331 /* check to insure all requests are idle */
332 for (row
= 0; row
< (c
->max_tag
/P9_ROW_MAXTAG
); row
++) {
333 for (col
= 0; col
< P9_ROW_MAXTAG
; col
++) {
334 if (c
->reqs
[row
][col
].status
!= REQ_STATUS_IDLE
) {
335 P9_DPRINTK(P9_DEBUG_MUX
,
336 "Attempting to cleanup non-free tag %d,%d\n",
338 /* TODO: delay execution of cleanup */
345 p9_idpool_put(0, c
->tagpool
); /* free reserved tag 0 */
346 p9_idpool_destroy(c
->tagpool
);
349 /* free requests associated with tags */
350 for (row
= 0; row
< (c
->max_tag
/P9_ROW_MAXTAG
); row
++) {
351 for (col
= 0; col
< P9_ROW_MAXTAG
; col
++) {
352 kfree(c
->reqs
[row
][col
].wq
);
353 kfree(c
->reqs
[row
][col
].tc
);
354 kfree(c
->reqs
[row
][col
].rc
);
362 * p9_free_req - free a request and clean-up as necessary
364 * r: request to release
368 static void p9_free_req(struct p9_client
*c
, struct p9_req_t
*r
)
370 int tag
= r
->tc
->tag
;
371 P9_DPRINTK(P9_DEBUG_MUX
, "clnt %p req %p tag: %d\n", c
, r
, tag
);
373 r
->status
= REQ_STATUS_IDLE
;
374 if (tag
!= P9_NOTAG
&& p9_idpool_check(tag
, c
->tagpool
))
375 p9_idpool_put(tag
, c
->tagpool
);
379 * p9_client_cb - call back from transport to client
381 * req: request received
384 void p9_client_cb(struct p9_client
*c
, struct p9_req_t
*req
)
386 P9_DPRINTK(P9_DEBUG_MUX
, " tag %d\n", req
->tc
->tag
);
388 P9_DPRINTK(P9_DEBUG_MUX
, "wakeup: %d\n", req
->tc
->tag
);
390 EXPORT_SYMBOL(p9_client_cb
);
393 * p9_parse_header - parse header arguments out of a packet
394 * @pdu: packet to parse
395 * @size: size of packet
396 * @type: type of request
397 * @tag: tag of packet
398 * @rewind: set if we need to rewind offset afterwards
402 p9_parse_header(struct p9_fcall
*pdu
, int32_t *size
, int8_t *type
, int16_t *tag
,
408 int offset
= pdu
->offset
;
415 err
= p9pdu_readf(pdu
, 0, "dbw", &r_size
, &r_type
, &r_tag
);
417 goto rewind_and_exit
;
423 P9_DPRINTK(P9_DEBUG_9P
, "<<< size=%d type: %d tag: %d\n", pdu
->size
,
436 pdu
->offset
= offset
;
439 EXPORT_SYMBOL(p9_parse_header
);
442 * p9_check_errors - check 9p packet for error return and process it
443 * @c: current client instance
444 * @req: request to parse and check for error conditions
446 * returns error code if one is discovered, otherwise returns 0
448 * this will have to be more complicated if we have multiple
452 static int p9_check_errors(struct p9_client
*c
, struct p9_req_t
*req
)
458 err
= p9_parse_header(req
->rc
, NULL
, &type
, NULL
, 0);
460 P9_DPRINTK(P9_DEBUG_ERROR
, "couldn't parse header %d\n", err
);
464 if (type
!= P9_RERROR
&& type
!= P9_RLERROR
)
467 if (!p9_is_proto_dotl(c
)) {
470 if (req
->tc
->pbuf_size
) {
471 /* Handle user buffers */
472 size_t len
= req
->rc
->size
- req
->rc
->offset
;
473 if (req
->tc
->pubuf
) {
475 err
= copy_from_user(
476 &req
->rc
->sdata
[req
->rc
->offset
],
477 req
->tc
->pubuf
, len
);
484 memmove(&req
->rc
->sdata
[req
->rc
->offset
],
485 req
->tc
->pkbuf
, len
);
488 err
= p9pdu_readf(req
->rc
, c
->proto_version
, "s?d",
493 if (p9_is_proto_dotu(c
))
496 if (!err
|| !IS_ERR_VALUE(err
)) {
497 err
= p9_errstr2errno(ename
, strlen(ename
));
499 P9_DPRINTK(P9_DEBUG_9P
, "<<< RERROR (%d) %s\n", -ecode
,
505 err
= p9pdu_readf(req
->rc
, c
->proto_version
, "d", &ecode
);
508 P9_DPRINTK(P9_DEBUG_9P
, "<<< RLERROR (%d)\n", -ecode
);
515 P9_DPRINTK(P9_DEBUG_ERROR
, "couldn't parse error%d\n", err
);
520 static struct p9_req_t
*
521 p9_client_rpc(struct p9_client
*c
, int8_t type
, const char *fmt
, ...);
524 * p9_client_flush - flush (cancel) a request
526 * @oldreq: request to cancel
528 * This sents a flush for a particular request and links
529 * the flush request to the original request. The current
530 * code only supports a single flush request although the protocol
531 * allows for multiple flush requests to be sent for a single request.
535 static int p9_client_flush(struct p9_client
*c
, struct p9_req_t
*oldreq
)
537 struct p9_req_t
*req
;
541 err
= p9_parse_header(oldreq
->tc
, NULL
, NULL
, &oldtag
, 1);
545 P9_DPRINTK(P9_DEBUG_9P
, ">>> TFLUSH tag %d\n", oldtag
);
547 req
= p9_client_rpc(c
, P9_TFLUSH
, "w", oldtag
);
552 /* if we haven't received a response for oldreq,
553 remove it from the list. */
555 if (oldreq
->status
== REQ_STATUS_FLSH
)
556 list_del(&oldreq
->req_list
);
557 spin_unlock(&c
->lock
);
564 * p9_client_rpc - issue a request and wait for a response
566 * @type: type of request
567 * @fmt: protocol format string (see protocol.c)
569 * Returns request structure (which client must free using p9_free_req)
572 static struct p9_req_t
*
573 p9_client_rpc(struct p9_client
*c
, int8_t type
, const char *fmt
, ...)
577 struct p9_req_t
*req
;
581 P9_DPRINTK(P9_DEBUG_MUX
, "client %p op %d\n", c
, type
);
583 /* we allow for any status other than disconnected */
584 if (c
->status
== Disconnected
)
585 return ERR_PTR(-EIO
);
587 /* if status is begin_disconnected we allow only clunk request */
588 if ((c
->status
== BeginDisconnect
) && (type
!= P9_TCLUNK
))
589 return ERR_PTR(-EIO
);
591 if (signal_pending(current
)) {
593 clear_thread_flag(TIF_SIGPENDING
);
598 if (type
!= P9_TVERSION
) {
599 tag
= p9_idpool_get(c
->tagpool
);
601 return ERR_PTR(-ENOMEM
);
604 req
= p9_tag_alloc(c
, tag
);
608 /* marshall the data */
609 p9pdu_prepare(req
->tc
, tag
, type
);
611 err
= p9pdu_vwritef(req
->tc
, c
->proto_version
, fmt
, ap
);
615 p9pdu_finalize(req
->tc
);
617 err
= c
->trans_mod
->request(c
, req
);
619 if (err
!= -ERESTARTSYS
&& err
!= -EFAULT
)
620 c
->status
= Disconnected
;
624 P9_DPRINTK(P9_DEBUG_MUX
, "wait %p tag: %d\n", req
->wq
, tag
);
625 err
= wait_event_interruptible(*req
->wq
,
626 req
->status
>= REQ_STATUS_RCVD
);
627 P9_DPRINTK(P9_DEBUG_MUX
, "wait %p tag: %d returned %d\n",
630 if (req
->status
== REQ_STATUS_ERROR
) {
631 P9_DPRINTK(P9_DEBUG_ERROR
, "req_status error %d\n", req
->t_err
);
635 if ((err
== -ERESTARTSYS
) && (c
->status
== Connected
)) {
636 P9_DPRINTK(P9_DEBUG_MUX
, "flushing\n");
638 clear_thread_flag(TIF_SIGPENDING
);
640 if (c
->trans_mod
->cancel(c
, req
))
641 p9_client_flush(c
, req
);
643 /* if we received the response anyway, don't signal error */
644 if (req
->status
== REQ_STATUS_RCVD
)
649 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
651 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
657 err
= p9_check_errors(c
, req
);
659 P9_DPRINTK(P9_DEBUG_MUX
, "exit: client %p op %d\n", c
, type
);
664 P9_DPRINTK(P9_DEBUG_MUX
, "exit: client %p op %d error: %d\n", c
, type
,
670 static struct p9_fid
*p9_fid_create(struct p9_client
*clnt
)
676 P9_DPRINTK(P9_DEBUG_FID
, "clnt %p\n", clnt
);
677 fid
= kmalloc(sizeof(struct p9_fid
), GFP_KERNEL
);
679 return ERR_PTR(-ENOMEM
);
681 ret
= p9_idpool_get(clnt
->fidpool
);
688 memset(&fid
->qid
, 0, sizeof(struct p9_qid
));
690 fid
->uid
= current_fsuid();
693 spin_lock_irqsave(&clnt
->lock
, flags
);
694 list_add(&fid
->flist
, &clnt
->fidlist
);
695 spin_unlock_irqrestore(&clnt
->lock
, flags
);
704 static void p9_fid_destroy(struct p9_fid
*fid
)
706 struct p9_client
*clnt
;
709 P9_DPRINTK(P9_DEBUG_FID
, "fid %d\n", fid
->fid
);
711 p9_idpool_put(fid
->fid
, clnt
->fidpool
);
712 spin_lock_irqsave(&clnt
->lock
, flags
);
713 list_del(&fid
->flist
);
714 spin_unlock_irqrestore(&clnt
->lock
, flags
);
719 static int p9_client_version(struct p9_client
*c
)
722 struct p9_req_t
*req
;
726 P9_DPRINTK(P9_DEBUG_9P
, ">>> TVERSION msize %d protocol %d\n",
727 c
->msize
, c
->proto_version
);
729 switch (c
->proto_version
) {
731 req
= p9_client_rpc(c
, P9_TVERSION
, "ds",
732 c
->msize
, "9P2000.L");
735 req
= p9_client_rpc(c
, P9_TVERSION
, "ds",
736 c
->msize
, "9P2000.u");
738 case p9_proto_legacy
:
739 req
= p9_client_rpc(c
, P9_TVERSION
, "ds",
750 err
= p9pdu_readf(req
->rc
, c
->proto_version
, "ds", &msize
, &version
);
752 P9_DPRINTK(P9_DEBUG_9P
, "version error %d\n", err
);
753 p9pdu_dump(1, req
->rc
);
757 P9_DPRINTK(P9_DEBUG_9P
, "<<< RVERSION msize %d %s\n", msize
, version
);
758 if (!strncmp(version
, "9P2000.L", 8))
759 c
->proto_version
= p9_proto_2000L
;
760 else if (!strncmp(version
, "9P2000.u", 8))
761 c
->proto_version
= p9_proto_2000u
;
762 else if (!strncmp(version
, "9P2000", 6))
763 c
->proto_version
= p9_proto_legacy
;
769 if (msize
< c
->msize
)
779 struct p9_client
*p9_client_create(const char *dev_name
, char *options
)
782 struct p9_client
*clnt
;
785 clnt
= kmalloc(sizeof(struct p9_client
), GFP_KERNEL
);
787 return ERR_PTR(-ENOMEM
);
789 clnt
->trans_mod
= NULL
;
791 spin_lock_init(&clnt
->lock
);
792 INIT_LIST_HEAD(&clnt
->fidlist
);
794 err
= p9_tag_init(clnt
);
798 err
= parse_opts(options
, clnt
);
800 goto destroy_tagpool
;
802 if (!clnt
->trans_mod
)
803 clnt
->trans_mod
= v9fs_get_default_trans();
805 if (clnt
->trans_mod
== NULL
) {
806 err
= -EPROTONOSUPPORT
;
807 P9_DPRINTK(P9_DEBUG_ERROR
,
808 "No transport defined or default transport\n");
809 goto destroy_tagpool
;
812 clnt
->fidpool
= p9_idpool_create();
813 if (IS_ERR(clnt
->fidpool
)) {
814 err
= PTR_ERR(clnt
->fidpool
);
818 P9_DPRINTK(P9_DEBUG_MUX
, "clnt %p trans %p msize %d protocol %d\n",
819 clnt
, clnt
->trans_mod
, clnt
->msize
, clnt
->proto_version
);
821 err
= clnt
->trans_mod
->create(clnt
, dev_name
, options
);
823 goto destroy_fidpool
;
825 if (clnt
->msize
> clnt
->trans_mod
->maxsize
)
826 clnt
->msize
= clnt
->trans_mod
->maxsize
;
828 err
= p9_client_version(clnt
);
835 clnt
->trans_mod
->close(clnt
);
837 p9_idpool_destroy(clnt
->fidpool
);
839 v9fs_put_trans(clnt
->trans_mod
);
841 p9_idpool_destroy(clnt
->tagpool
);
846 EXPORT_SYMBOL(p9_client_create
);
848 void p9_client_destroy(struct p9_client
*clnt
)
850 struct p9_fid
*fid
, *fidptr
;
852 P9_DPRINTK(P9_DEBUG_MUX
, "clnt %p\n", clnt
);
855 clnt
->trans_mod
->close(clnt
);
857 v9fs_put_trans(clnt
->trans_mod
);
859 list_for_each_entry_safe(fid
, fidptr
, &clnt
->fidlist
, flist
) {
860 printk(KERN_INFO
"Found fid %d not clunked\n", fid
->fid
);
865 p9_idpool_destroy(clnt
->fidpool
);
867 p9_tag_cleanup(clnt
);
871 EXPORT_SYMBOL(p9_client_destroy
);
873 void p9_client_disconnect(struct p9_client
*clnt
)
875 P9_DPRINTK(P9_DEBUG_9P
, "clnt %p\n", clnt
);
876 clnt
->status
= Disconnected
;
878 EXPORT_SYMBOL(p9_client_disconnect
);
880 void p9_client_begin_disconnect(struct p9_client
*clnt
)
882 P9_DPRINTK(P9_DEBUG_9P
, "clnt %p\n", clnt
);
883 clnt
->status
= BeginDisconnect
;
885 EXPORT_SYMBOL(p9_client_begin_disconnect
);
887 struct p9_fid
*p9_client_attach(struct p9_client
*clnt
, struct p9_fid
*afid
,
888 char *uname
, u32 n_uname
, char *aname
)
891 struct p9_req_t
*req
;
895 P9_DPRINTK(P9_DEBUG_9P
, ">>> TATTACH afid %d uname %s aname %s\n",
896 afid
? afid
->fid
: -1, uname
, aname
);
899 fid
= p9_fid_create(clnt
);
906 req
= p9_client_rpc(clnt
, P9_TATTACH
, "ddss?d", fid
->fid
,
907 afid
? afid
->fid
: P9_NOFID
, uname
, aname
, n_uname
);
913 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "Q", &qid
);
915 p9pdu_dump(1, req
->rc
);
916 p9_free_req(clnt
, req
);
920 P9_DPRINTK(P9_DEBUG_9P
, "<<< RATTACH qid %x.%llx.%x\n",
922 (unsigned long long)qid
.path
,
925 memmove(&fid
->qid
, &qid
, sizeof(struct p9_qid
));
927 p9_free_req(clnt
, req
);
935 EXPORT_SYMBOL(p9_client_attach
);
937 struct p9_fid
*p9_client_walk(struct p9_fid
*oldfid
, uint16_t nwname
,
938 char **wnames
, int clone
)
941 struct p9_client
*clnt
;
943 struct p9_qid
*wqids
;
944 struct p9_req_t
*req
;
945 uint16_t nwqids
, count
;
951 fid
= p9_fid_create(clnt
);
958 fid
->uid
= oldfid
->uid
;
963 P9_DPRINTK(P9_DEBUG_9P
, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n",
964 oldfid
->fid
, fid
->fid
, nwname
, wnames
? wnames
[0] : NULL
);
966 req
= p9_client_rpc(clnt
, P9_TWALK
, "ddT", oldfid
->fid
, fid
->fid
,
973 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "R", &nwqids
, &wqids
);
975 p9pdu_dump(1, req
->rc
);
976 p9_free_req(clnt
, req
);
979 p9_free_req(clnt
, req
);
981 P9_DPRINTK(P9_DEBUG_9P
, "<<< RWALK nwqid %d:\n", nwqids
);
983 if (nwqids
!= nwname
) {
988 for (count
= 0; count
< nwqids
; count
++)
989 P9_DPRINTK(P9_DEBUG_9P
, "<<< [%d] %x.%llx.%x\n",
990 count
, wqids
[count
].type
,
991 (unsigned long long)wqids
[count
].path
,
992 wqids
[count
].version
);
995 memmove(&fid
->qid
, &wqids
[nwqids
- 1], sizeof(struct p9_qid
));
997 fid
->qid
= oldfid
->qid
;
1004 p9_client_clunk(fid
);
1008 if (fid
&& (fid
!= oldfid
))
1009 p9_fid_destroy(fid
);
1011 return ERR_PTR(err
);
1013 EXPORT_SYMBOL(p9_client_walk
);
1015 int p9_client_open(struct p9_fid
*fid
, int mode
)
1018 struct p9_client
*clnt
;
1019 struct p9_req_t
*req
;
1024 P9_DPRINTK(P9_DEBUG_9P
, ">>> %s fid %d mode %d\n",
1025 p9_is_proto_dotl(clnt
) ? "TLOPEN" : "TOPEN", fid
->fid
, mode
);
1028 if (fid
->mode
!= -1)
1031 if (p9_is_proto_dotl(clnt
))
1032 req
= p9_client_rpc(clnt
, P9_TLOPEN
, "dd", fid
->fid
, mode
);
1034 req
= p9_client_rpc(clnt
, P9_TOPEN
, "db", fid
->fid
, mode
);
1040 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "Qd", &qid
, &iounit
);
1042 p9pdu_dump(1, req
->rc
);
1043 goto free_and_error
;
1046 P9_DPRINTK(P9_DEBUG_9P
, "<<< %s qid %x.%llx.%x iounit %x\n",
1047 p9_is_proto_dotl(clnt
) ? "RLOPEN" : "ROPEN", qid
.type
,
1048 (unsigned long long)qid
.path
, qid
.version
, iounit
);
1051 fid
->iounit
= iounit
;
1054 p9_free_req(clnt
, req
);
1058 EXPORT_SYMBOL(p9_client_open
);
1060 int p9_client_create_dotl(struct p9_fid
*ofid
, char *name
, u32 flags
, u32 mode
,
1061 gid_t gid
, struct p9_qid
*qid
)
1064 struct p9_client
*clnt
;
1065 struct p9_req_t
*req
;
1068 P9_DPRINTK(P9_DEBUG_9P
,
1069 ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
1070 ofid
->fid
, name
, flags
, mode
, gid
);
1073 if (ofid
->mode
!= -1)
1076 req
= p9_client_rpc(clnt
, P9_TLCREATE
, "dsddd", ofid
->fid
, name
, flags
,
1083 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "Qd", qid
, &iounit
);
1085 p9pdu_dump(1, req
->rc
);
1086 goto free_and_error
;
1089 P9_DPRINTK(P9_DEBUG_9P
, "<<< RLCREATE qid %x.%llx.%x iounit %x\n",
1091 (unsigned long long)qid
->path
,
1092 qid
->version
, iounit
);
1095 ofid
->iounit
= iounit
;
1098 p9_free_req(clnt
, req
);
1102 EXPORT_SYMBOL(p9_client_create_dotl
);
1104 int p9_client_fcreate(struct p9_fid
*fid
, char *name
, u32 perm
, int mode
,
1108 struct p9_client
*clnt
;
1109 struct p9_req_t
*req
;
1113 P9_DPRINTK(P9_DEBUG_9P
, ">>> TCREATE fid %d name %s perm %d mode %d\n",
1114 fid
->fid
, name
, perm
, mode
);
1118 if (fid
->mode
!= -1)
1121 req
= p9_client_rpc(clnt
, P9_TCREATE
, "dsdb?s", fid
->fid
, name
, perm
,
1128 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "Qd", &qid
, &iounit
);
1130 p9pdu_dump(1, req
->rc
);
1131 goto free_and_error
;
1134 P9_DPRINTK(P9_DEBUG_9P
, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
1136 (unsigned long long)qid
.path
,
1137 qid
.version
, iounit
);
1140 fid
->iounit
= iounit
;
1143 p9_free_req(clnt
, req
);
1147 EXPORT_SYMBOL(p9_client_fcreate
);
1149 int p9_client_symlink(struct p9_fid
*dfid
, char *name
, char *symtgt
, gid_t gid
,
1153 struct p9_client
*clnt
;
1154 struct p9_req_t
*req
;
1156 P9_DPRINTK(P9_DEBUG_9P
, ">>> TSYMLINK dfid %d name %s symtgt %s\n",
1157 dfid
->fid
, name
, symtgt
);
1160 req
= p9_client_rpc(clnt
, P9_TSYMLINK
, "dssd", dfid
->fid
, name
, symtgt
,
1167 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "Q", qid
);
1169 p9pdu_dump(1, req
->rc
);
1170 goto free_and_error
;
1173 P9_DPRINTK(P9_DEBUG_9P
, "<<< RSYMLINK qid %x.%llx.%x\n",
1174 qid
->type
, (unsigned long long)qid
->path
, qid
->version
);
1177 p9_free_req(clnt
, req
);
1181 EXPORT_SYMBOL(p9_client_symlink
);
1183 int p9_client_link(struct p9_fid
*dfid
, struct p9_fid
*oldfid
, char *newname
)
1185 struct p9_client
*clnt
;
1186 struct p9_req_t
*req
;
1188 P9_DPRINTK(P9_DEBUG_9P
, ">>> TLINK dfid %d oldfid %d newname %s\n",
1189 dfid
->fid
, oldfid
->fid
, newname
);
1191 req
= p9_client_rpc(clnt
, P9_TLINK
, "dds", dfid
->fid
, oldfid
->fid
,
1194 return PTR_ERR(req
);
1196 P9_DPRINTK(P9_DEBUG_9P
, "<<< RLINK\n");
1197 p9_free_req(clnt
, req
);
1200 EXPORT_SYMBOL(p9_client_link
);
1202 int p9_client_fsync(struct p9_fid
*fid
, int datasync
)
1205 struct p9_client
*clnt
;
1206 struct p9_req_t
*req
;
1208 P9_DPRINTK(P9_DEBUG_9P
, ">>> TFSYNC fid %d datasync:%d\n",
1209 fid
->fid
, datasync
);
1213 req
= p9_client_rpc(clnt
, P9_TFSYNC
, "dd", fid
->fid
, datasync
);
1219 P9_DPRINTK(P9_DEBUG_9P
, "<<< RFSYNC fid %d\n", fid
->fid
);
1221 p9_free_req(clnt
, req
);
1226 EXPORT_SYMBOL(p9_client_fsync
);
1228 int p9_client_clunk(struct p9_fid
*fid
)
1231 struct p9_client
*clnt
;
1232 struct p9_req_t
*req
;
1235 P9_EPRINTK(KERN_WARNING
, "Trying to clunk with NULL fid\n");
1240 P9_DPRINTK(P9_DEBUG_9P
, ">>> TCLUNK fid %d\n", fid
->fid
);
1244 req
= p9_client_rpc(clnt
, P9_TCLUNK
, "d", fid
->fid
);
1250 P9_DPRINTK(P9_DEBUG_9P
, "<<< RCLUNK fid %d\n", fid
->fid
);
1252 p9_free_req(clnt
, req
);
1255 * Fid is not valid even after a failed clunk
1257 p9_fid_destroy(fid
);
1260 EXPORT_SYMBOL(p9_client_clunk
);
1262 int p9_client_remove(struct p9_fid
*fid
)
1265 struct p9_client
*clnt
;
1266 struct p9_req_t
*req
;
1268 P9_DPRINTK(P9_DEBUG_9P
, ">>> TREMOVE fid %d\n", fid
->fid
);
1272 req
= p9_client_rpc(clnt
, P9_TREMOVE
, "d", fid
->fid
);
1278 P9_DPRINTK(P9_DEBUG_9P
, "<<< RREMOVE fid %d\n", fid
->fid
);
1280 p9_free_req(clnt
, req
);
1282 p9_fid_destroy(fid
);
1285 EXPORT_SYMBOL(p9_client_remove
);
1288 p9_client_read(struct p9_fid
*fid
, char *data
, char __user
*udata
, u64 offset
,
1292 struct p9_client
*clnt
;
1293 struct p9_req_t
*req
;
1296 P9_DPRINTK(P9_DEBUG_9P
, ">>> TREAD fid %d offset %llu %d\n", fid
->fid
,
1297 (long long unsigned) offset
, count
);
1301 rsize
= fid
->iounit
;
1302 if (!rsize
|| rsize
> clnt
->msize
-P9_IOHDRSZ
)
1303 rsize
= clnt
->msize
- P9_IOHDRSZ
;
1308 /* Don't bother zerocopy for small IO (< 1024) */
1309 if (((clnt
->trans_mod
->pref
& P9_TRANS_PREF_PAYLOAD_MASK
) ==
1310 P9_TRANS_PREF_PAYLOAD_SEP
) && (rsize
> 1024)) {
1311 req
= p9_client_rpc(clnt
, P9_TREAD
, "dqE", fid
->fid
, offset
,
1312 rsize
, data
, udata
);
1314 req
= p9_client_rpc(clnt
, P9_TREAD
, "dqd", fid
->fid
, offset
,
1322 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "D", &count
, &dataptr
);
1324 p9pdu_dump(1, req
->rc
);
1325 goto free_and_error
;
1328 P9_DPRINTK(P9_DEBUG_9P
, "<<< RREAD count %d\n", count
);
1330 if (!req
->tc
->pbuf_size
) {
1332 memmove(data
, dataptr
, count
);
1334 err
= copy_to_user(udata
, dataptr
, count
);
1337 goto free_and_error
;
1341 p9_free_req(clnt
, req
);
1345 p9_free_req(clnt
, req
);
1349 EXPORT_SYMBOL(p9_client_read
);
1352 p9_client_write(struct p9_fid
*fid
, char *data
, const char __user
*udata
,
1353 u64 offset
, u32 count
)
1356 struct p9_client
*clnt
;
1357 struct p9_req_t
*req
;
1359 P9_DPRINTK(P9_DEBUG_9P
, ">>> TWRITE fid %d offset %llu count %d\n",
1360 fid
->fid
, (long long unsigned) offset
, count
);
1364 rsize
= fid
->iounit
;
1365 if (!rsize
|| rsize
> clnt
->msize
-P9_IOHDRSZ
)
1366 rsize
= clnt
->msize
- P9_IOHDRSZ
;
1371 /* Don't bother zerocopy form small IO (< 1024) */
1372 if (((clnt
->trans_mod
->pref
& P9_TRANS_PREF_PAYLOAD_MASK
) ==
1373 P9_TRANS_PREF_PAYLOAD_SEP
) && (rsize
> 1024)) {
1374 req
= p9_client_rpc(clnt
, P9_TWRITE
, "dqE", fid
->fid
, offset
,
1375 rsize
, data
, udata
);
1379 req
= p9_client_rpc(clnt
, P9_TWRITE
, "dqD", fid
->fid
,
1380 offset
, rsize
, data
);
1382 req
= p9_client_rpc(clnt
, P9_TWRITE
, "dqU", fid
->fid
,
1383 offset
, rsize
, udata
);
1390 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "d", &count
);
1392 p9pdu_dump(1, req
->rc
);
1393 goto free_and_error
;
1396 P9_DPRINTK(P9_DEBUG_9P
, "<<< RWRITE count %d\n", count
);
1398 p9_free_req(clnt
, req
);
1402 p9_free_req(clnt
, req
);
1406 EXPORT_SYMBOL(p9_client_write
);
1408 struct p9_wstat
*p9_client_stat(struct p9_fid
*fid
)
1411 struct p9_client
*clnt
;
1412 struct p9_wstat
*ret
= kmalloc(sizeof(struct p9_wstat
), GFP_KERNEL
);
1413 struct p9_req_t
*req
;
1416 P9_DPRINTK(P9_DEBUG_9P
, ">>> TSTAT fid %d\n", fid
->fid
);
1419 return ERR_PTR(-ENOMEM
);
1424 req
= p9_client_rpc(clnt
, P9_TSTAT
, "d", fid
->fid
);
1430 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "wS", &ignored
, ret
);
1432 p9pdu_dump(1, req
->rc
);
1433 p9_free_req(clnt
, req
);
1437 P9_DPRINTK(P9_DEBUG_9P
,
1438 "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1439 "<<< mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1440 "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1441 "<<< uid=%d gid=%d n_muid=%d\n",
1442 ret
->size
, ret
->type
, ret
->dev
, ret
->qid
.type
,
1443 (unsigned long long)ret
->qid
.path
, ret
->qid
.version
, ret
->mode
,
1444 ret
->atime
, ret
->mtime
, (unsigned long long)ret
->length
,
1445 ret
->name
, ret
->uid
, ret
->gid
, ret
->muid
, ret
->extension
,
1446 ret
->n_uid
, ret
->n_gid
, ret
->n_muid
);
1448 p9_free_req(clnt
, req
);
1453 return ERR_PTR(err
);
1455 EXPORT_SYMBOL(p9_client_stat
);
1457 struct p9_stat_dotl
*p9_client_getattr_dotl(struct p9_fid
*fid
,
1461 struct p9_client
*clnt
;
1462 struct p9_stat_dotl
*ret
= kmalloc(sizeof(struct p9_stat_dotl
),
1464 struct p9_req_t
*req
;
1466 P9_DPRINTK(P9_DEBUG_9P
, ">>> TGETATTR fid %d, request_mask %lld\n",
1467 fid
->fid
, request_mask
);
1470 return ERR_PTR(-ENOMEM
);
1475 req
= p9_client_rpc(clnt
, P9_TGETATTR
, "dq", fid
->fid
, request_mask
);
1481 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "A", ret
);
1483 p9pdu_dump(1, req
->rc
);
1484 p9_free_req(clnt
, req
);
1488 P9_DPRINTK(P9_DEBUG_9P
,
1489 "<<< RGETATTR st_result_mask=%lld\n"
1490 "<<< qid=%x.%llx.%x\n"
1491 "<<< st_mode=%8.8x st_nlink=%llu\n"
1492 "<<< st_uid=%d st_gid=%d\n"
1493 "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n"
1494 "<<< st_atime_sec=%lld st_atime_nsec=%lld\n"
1495 "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n"
1496 "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n"
1497 "<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
1498 "<<< st_gen=%lld st_data_version=%lld",
1499 ret
->st_result_mask
, ret
->qid
.type
, ret
->qid
.path
,
1500 ret
->qid
.version
, ret
->st_mode
, ret
->st_nlink
, ret
->st_uid
,
1501 ret
->st_gid
, ret
->st_rdev
, ret
->st_size
, ret
->st_blksize
,
1502 ret
->st_blocks
, ret
->st_atime_sec
, ret
->st_atime_nsec
,
1503 ret
->st_mtime_sec
, ret
->st_mtime_nsec
, ret
->st_ctime_sec
,
1504 ret
->st_ctime_nsec
, ret
->st_btime_sec
, ret
->st_btime_nsec
,
1505 ret
->st_gen
, ret
->st_data_version
);
1507 p9_free_req(clnt
, req
);
1512 return ERR_PTR(err
);
1514 EXPORT_SYMBOL(p9_client_getattr_dotl
);
1516 static int p9_client_statsize(struct p9_wstat
*wst
, int proto_version
)
1520 /* NOTE: size shouldn't include its own length */
1521 /* size[2] type[2] dev[4] qid[13] */
1522 /* mode[4] atime[4] mtime[4] length[8]*/
1523 /* name[s] uid[s] gid[s] muid[s] */
1524 ret
= 2+4+13+4+4+4+8+2+2+2+2;
1527 ret
+= strlen(wst
->name
);
1529 ret
+= strlen(wst
->uid
);
1531 ret
+= strlen(wst
->gid
);
1533 ret
+= strlen(wst
->muid
);
1535 if ((proto_version
== p9_proto_2000u
) ||
1536 (proto_version
== p9_proto_2000L
)) {
1537 ret
+= 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
1539 ret
+= strlen(wst
->extension
);
1545 int p9_client_wstat(struct p9_fid
*fid
, struct p9_wstat
*wst
)
1548 struct p9_req_t
*req
;
1549 struct p9_client
*clnt
;
1553 wst
->size
= p9_client_statsize(wst
, clnt
->proto_version
);
1554 P9_DPRINTK(P9_DEBUG_9P
, ">>> TWSTAT fid %d\n", fid
->fid
);
1555 P9_DPRINTK(P9_DEBUG_9P
,
1556 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1557 " mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1558 " name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1559 " uid=%d gid=%d n_muid=%d\n",
1560 wst
->size
, wst
->type
, wst
->dev
, wst
->qid
.type
,
1561 (unsigned long long)wst
->qid
.path
, wst
->qid
.version
, wst
->mode
,
1562 wst
->atime
, wst
->mtime
, (unsigned long long)wst
->length
,
1563 wst
->name
, wst
->uid
, wst
->gid
, wst
->muid
, wst
->extension
,
1564 wst
->n_uid
, wst
->n_gid
, wst
->n_muid
);
1566 req
= p9_client_rpc(clnt
, P9_TWSTAT
, "dwS", fid
->fid
, wst
->size
+2, wst
);
1572 P9_DPRINTK(P9_DEBUG_9P
, "<<< RWSTAT fid %d\n", fid
->fid
);
1574 p9_free_req(clnt
, req
);
1578 EXPORT_SYMBOL(p9_client_wstat
);
1580 int p9_client_setattr(struct p9_fid
*fid
, struct p9_iattr_dotl
*p9attr
)
1583 struct p9_req_t
*req
;
1584 struct p9_client
*clnt
;
1588 P9_DPRINTK(P9_DEBUG_9P
, ">>> TSETATTR fid %d\n", fid
->fid
);
1589 P9_DPRINTK(P9_DEBUG_9P
,
1590 " valid=%x mode=%x uid=%d gid=%d size=%lld\n"
1591 " atime_sec=%lld atime_nsec=%lld\n"
1592 " mtime_sec=%lld mtime_nsec=%lld\n",
1593 p9attr
->valid
, p9attr
->mode
, p9attr
->uid
, p9attr
->gid
,
1594 p9attr
->size
, p9attr
->atime_sec
, p9attr
->atime_nsec
,
1595 p9attr
->mtime_sec
, p9attr
->mtime_nsec
);
1597 req
= p9_client_rpc(clnt
, P9_TSETATTR
, "dI", fid
->fid
, p9attr
);
1603 P9_DPRINTK(P9_DEBUG_9P
, "<<< RSETATTR fid %d\n", fid
->fid
);
1604 p9_free_req(clnt
, req
);
1608 EXPORT_SYMBOL(p9_client_setattr
);
1610 int p9_client_statfs(struct p9_fid
*fid
, struct p9_rstatfs
*sb
)
1613 struct p9_req_t
*req
;
1614 struct p9_client
*clnt
;
1619 P9_DPRINTK(P9_DEBUG_9P
, ">>> TSTATFS fid %d\n", fid
->fid
);
1621 req
= p9_client_rpc(clnt
, P9_TSTATFS
, "d", fid
->fid
);
1627 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "ddqqqqqqd", &sb
->type
,
1628 &sb
->bsize
, &sb
->blocks
, &sb
->bfree
, &sb
->bavail
,
1629 &sb
->files
, &sb
->ffree
, &sb
->fsid
, &sb
->namelen
);
1631 p9pdu_dump(1, req
->rc
);
1632 p9_free_req(clnt
, req
);
1636 P9_DPRINTK(P9_DEBUG_9P
, "<<< RSTATFS fid %d type 0x%lx bsize %ld "
1637 "blocks %llu bfree %llu bavail %llu files %llu ffree %llu "
1638 "fsid %llu namelen %ld\n",
1639 fid
->fid
, (long unsigned int)sb
->type
, (long int)sb
->bsize
,
1640 sb
->blocks
, sb
->bfree
, sb
->bavail
, sb
->files
, sb
->ffree
,
1641 sb
->fsid
, (long int)sb
->namelen
);
1643 p9_free_req(clnt
, req
);
1647 EXPORT_SYMBOL(p9_client_statfs
);
1649 int p9_client_rename(struct p9_fid
*fid
, struct p9_fid
*newdirfid
, char *name
)
1652 struct p9_req_t
*req
;
1653 struct p9_client
*clnt
;
1658 P9_DPRINTK(P9_DEBUG_9P
, ">>> TRENAME fid %d newdirfid %d name %s\n",
1659 fid
->fid
, newdirfid
->fid
, name
);
1661 req
= p9_client_rpc(clnt
, P9_TRENAME
, "dds", fid
->fid
,
1662 newdirfid
->fid
, name
);
1668 P9_DPRINTK(P9_DEBUG_9P
, "<<< RRENAME fid %d\n", fid
->fid
);
1670 p9_free_req(clnt
, req
);
1674 EXPORT_SYMBOL(p9_client_rename
);
1677 * An xattrwalk without @attr_name gives the fid for the lisxattr namespace
1679 struct p9_fid
*p9_client_xattrwalk(struct p9_fid
*file_fid
,
1680 const char *attr_name
, u64
*attr_size
)
1683 struct p9_req_t
*req
;
1684 struct p9_client
*clnt
;
1685 struct p9_fid
*attr_fid
;
1688 clnt
= file_fid
->clnt
;
1689 attr_fid
= p9_fid_create(clnt
);
1690 if (IS_ERR(attr_fid
)) {
1691 err
= PTR_ERR(attr_fid
);
1695 P9_DPRINTK(P9_DEBUG_9P
,
1696 ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n",
1697 file_fid
->fid
, attr_fid
->fid
, attr_name
);
1699 req
= p9_client_rpc(clnt
, P9_TXATTRWALK
, "dds",
1700 file_fid
->fid
, attr_fid
->fid
, attr_name
);
1705 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "q", attr_size
);
1707 p9pdu_dump(1, req
->rc
);
1708 p9_free_req(clnt
, req
);
1711 p9_free_req(clnt
, req
);
1712 P9_DPRINTK(P9_DEBUG_9P
, "<<< RXATTRWALK fid %d size %llu\n",
1713 attr_fid
->fid
, *attr_size
);
1716 p9_client_clunk(attr_fid
);
1719 if (attr_fid
&& (attr_fid
!= file_fid
))
1720 p9_fid_destroy(attr_fid
);
1722 return ERR_PTR(err
);
1724 EXPORT_SYMBOL_GPL(p9_client_xattrwalk
);
1726 int p9_client_xattrcreate(struct p9_fid
*fid
, const char *name
,
1727 u64 attr_size
, int flags
)
1730 struct p9_req_t
*req
;
1731 struct p9_client
*clnt
;
1733 P9_DPRINTK(P9_DEBUG_9P
,
1734 ">>> TXATTRCREATE fid %d name %s size %lld flag %d\n",
1735 fid
->fid
, name
, (long long)attr_size
, flags
);
1738 req
= p9_client_rpc(clnt
, P9_TXATTRCREATE
, "dsqd",
1739 fid
->fid
, name
, attr_size
, flags
);
1744 P9_DPRINTK(P9_DEBUG_9P
, "<<< RXATTRCREATE fid %d\n", fid
->fid
);
1745 p9_free_req(clnt
, req
);
1749 EXPORT_SYMBOL_GPL(p9_client_xattrcreate
);
1751 int p9_client_readdir(struct p9_fid
*fid
, char *data
, u32 count
, u64 offset
)
1754 struct p9_client
*clnt
;
1755 struct p9_req_t
*req
;
1758 P9_DPRINTK(P9_DEBUG_9P
, ">>> TREADDIR fid %d offset %llu count %d\n",
1759 fid
->fid
, (long long unsigned) offset
, count
);
1764 rsize
= fid
->iounit
;
1765 if (!rsize
|| rsize
> clnt
->msize
-P9_READDIRHDRSZ
)
1766 rsize
= clnt
->msize
- P9_READDIRHDRSZ
;
1771 if ((clnt
->trans_mod
->pref
& P9_TRANS_PREF_PAYLOAD_MASK
) ==
1772 P9_TRANS_PREF_PAYLOAD_SEP
) {
1773 req
= p9_client_rpc(clnt
, P9_TREADDIR
, "dqF", fid
->fid
,
1774 offset
, rsize
, data
);
1776 req
= p9_client_rpc(clnt
, P9_TREADDIR
, "dqd", fid
->fid
,
1784 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "D", &count
, &dataptr
);
1786 p9pdu_dump(1, req
->rc
);
1787 goto free_and_error
;
1790 P9_DPRINTK(P9_DEBUG_9P
, "<<< RREADDIR count %d\n", count
);
1792 if (!req
->tc
->pbuf_size
&& data
)
1793 memmove(data
, dataptr
, count
);
1795 p9_free_req(clnt
, req
);
1799 p9_free_req(clnt
, req
);
1803 EXPORT_SYMBOL(p9_client_readdir
);
1805 int p9_client_mknod_dotl(struct p9_fid
*fid
, char *name
, int mode
,
1806 dev_t rdev
, gid_t gid
, struct p9_qid
*qid
)
1809 struct p9_client
*clnt
;
1810 struct p9_req_t
*req
;
1814 P9_DPRINTK(P9_DEBUG_9P
, ">>> TMKNOD fid %d name %s mode %d major %d "
1815 "minor %d\n", fid
->fid
, name
, mode
, MAJOR(rdev
), MINOR(rdev
));
1816 req
= p9_client_rpc(clnt
, P9_TMKNOD
, "dsdddd", fid
->fid
, name
, mode
,
1817 MAJOR(rdev
), MINOR(rdev
), gid
);
1819 return PTR_ERR(req
);
1821 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "Q", qid
);
1823 p9pdu_dump(1, req
->rc
);
1826 P9_DPRINTK(P9_DEBUG_9P
, "<<< RMKNOD qid %x.%llx.%x\n", qid
->type
,
1827 (unsigned long long)qid
->path
, qid
->version
);
1830 p9_free_req(clnt
, req
);
1834 EXPORT_SYMBOL(p9_client_mknod_dotl
);
1836 int p9_client_mkdir_dotl(struct p9_fid
*fid
, char *name
, int mode
,
1837 gid_t gid
, struct p9_qid
*qid
)
1840 struct p9_client
*clnt
;
1841 struct p9_req_t
*req
;
1845 P9_DPRINTK(P9_DEBUG_9P
, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
1846 fid
->fid
, name
, mode
, gid
);
1847 req
= p9_client_rpc(clnt
, P9_TMKDIR
, "dsdd", fid
->fid
, name
, mode
,
1850 return PTR_ERR(req
);
1852 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "Q", qid
);
1854 p9pdu_dump(1, req
->rc
);
1857 P9_DPRINTK(P9_DEBUG_9P
, "<<< RMKDIR qid %x.%llx.%x\n", qid
->type
,
1858 (unsigned long long)qid
->path
, qid
->version
);
1861 p9_free_req(clnt
, req
);
1865 EXPORT_SYMBOL(p9_client_mkdir_dotl
);
1867 int p9_client_lock_dotl(struct p9_fid
*fid
, struct p9_flock
*flock
, u8
*status
)
1870 struct p9_client
*clnt
;
1871 struct p9_req_t
*req
;
1875 P9_DPRINTK(P9_DEBUG_9P
, ">>> TLOCK fid %d type %i flags %d "
1876 "start %lld length %lld proc_id %d client_id %s\n",
1877 fid
->fid
, flock
->type
, flock
->flags
, flock
->start
,
1878 flock
->length
, flock
->proc_id
, flock
->client_id
);
1880 req
= p9_client_rpc(clnt
, P9_TLOCK
, "dbdqqds", fid
->fid
, flock
->type
,
1881 flock
->flags
, flock
->start
, flock
->length
,
1882 flock
->proc_id
, flock
->client_id
);
1885 return PTR_ERR(req
);
1887 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "b", status
);
1889 p9pdu_dump(1, req
->rc
);
1892 P9_DPRINTK(P9_DEBUG_9P
, "<<< RLOCK status %i\n", *status
);
1894 p9_free_req(clnt
, req
);
1898 EXPORT_SYMBOL(p9_client_lock_dotl
);
1900 int p9_client_getlock_dotl(struct p9_fid
*fid
, struct p9_getlock
*glock
)
1903 struct p9_client
*clnt
;
1904 struct p9_req_t
*req
;
1908 P9_DPRINTK(P9_DEBUG_9P
, ">>> TGETLOCK fid %d, type %i start %lld "
1909 "length %lld proc_id %d client_id %s\n", fid
->fid
, glock
->type
,
1910 glock
->start
, glock
->length
, glock
->proc_id
, glock
->client_id
);
1912 req
= p9_client_rpc(clnt
, P9_TGETLOCK
, "dbqqds", fid
->fid
, glock
->type
,
1913 glock
->start
, glock
->length
, glock
->proc_id
, glock
->client_id
);
1916 return PTR_ERR(req
);
1918 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "bqqds", &glock
->type
,
1919 &glock
->start
, &glock
->length
, &glock
->proc_id
,
1922 p9pdu_dump(1, req
->rc
);
1925 P9_DPRINTK(P9_DEBUG_9P
, "<<< RGETLOCK type %i start %lld length %lld "
1926 "proc_id %d client_id %s\n", glock
->type
, glock
->start
,
1927 glock
->length
, glock
->proc_id
, glock
->client_id
);
1929 p9_free_req(clnt
, req
);
1932 EXPORT_SYMBOL(p9_client_getlock_dotl
);
1934 int p9_client_readlink(struct p9_fid
*fid
, char **target
)
1937 struct p9_client
*clnt
;
1938 struct p9_req_t
*req
;
1942 P9_DPRINTK(P9_DEBUG_9P
, ">>> TREADLINK fid %d\n", fid
->fid
);
1944 req
= p9_client_rpc(clnt
, P9_TREADLINK
, "d", fid
->fid
);
1946 return PTR_ERR(req
);
1948 err
= p9pdu_readf(req
->rc
, clnt
->proto_version
, "s", target
);
1950 p9pdu_dump(1, req
->rc
);
1953 P9_DPRINTK(P9_DEBUG_9P
, "<<< RREADLINK target %s\n", *target
);
1955 p9_free_req(clnt
, req
);
1958 EXPORT_SYMBOL(p9_client_readlink
);