static void complete_transaction(struct fw_card *card, int rcode, void *payload, size_t length, void *data) { struct outbound_transaction_event *e = data; struct fw_cdev_event_response *rsp = &e->response; struct client *client = e->client; unsigned long flags; if (length < rsp->length) rsp->length = length; if (rcode == RCODE_COMPLETE) memcpy(rsp->data, payload, rsp->length); spin_lock_irqsave(&client->lock, flags); /* * 1. If called while in shutdown, the idr tree must be left untouched. * The idr handle will be removed and the client reference will be * dropped later. * 2. If the call chain was release_client_resource -> * release_transaction -> complete_transaction (instead of a normal * conclusion of the transaction), i.e. if this resource was already * unregistered from the idr, the client reference will be dropped * by release_client_resource and we must not drop it here. */ if (!client->in_shutdown && idr_find(&client->resource_idr, e->r.resource.handle)) { idr_remove(&client->resource_idr, e->r.resource.handle); /* Drop the idr's reference */ client_put(client); } spin_unlock_irqrestore(&client->lock, flags); rsp->type = FW_CDEV_EVENT_RESPONSE; rsp->rcode = rcode; /* * In the case that sizeof(*rsp) doesn't align with the position of the * data, and the read is short, preserve an extra copy of the data * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless * for short reads and some apps depended on it, this is both safe * and prudent for compatibility. */ if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data)) queue_event(client, &e->event, rsp, sizeof(*rsp), rsp->data, rsp->length); else queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0); /* Drop the transaction callback's reference */ client_put(client); }
static int release_client_resource(struct client *client, u32 handle, client_resource_release_fn_t release, struct client_resource **resource) { struct client_resource *r; spin_lock_irq(&client->lock); if (client->in_shutdown) r = NULL; else r = idr_find(&client->resource_idr, handle); if (r && r->release == release) idr_remove(&client->resource_idr, handle); spin_unlock_irq(&client->lock); if (!(r && r->release == release)) return -EINVAL; if (resource) *resource = r; else r->release(client, r); client_put(client); return 0; }
static int fw_device_op_release(struct inode *inode, struct file *file) { struct client *client = file->private_data; struct event *e, *next_e; mutex_lock(&client->device->client_list_mutex); list_del(&client->link); mutex_unlock(&client->device->client_list_mutex); if (client->iso_context) fw_iso_context_destroy(client->iso_context); if (client->buffer.pages) fw_iso_buffer_destroy(&client->buffer, client->device->card); /* Freeze client->resource_idr and client->event_list */ spin_lock_irq(&client->lock); client->in_shutdown = true; spin_unlock_irq(&client->lock); idr_for_each(&client->resource_idr, shutdown_resource, client); idr_remove_all(&client->resource_idr); idr_destroy(&client->resource_idr); list_for_each_entry_safe(e, next_e, &client->event_list, link) kfree(e); client_put(client); return 0; }
static int shutdown_resource(int id, void *p, void *data) { struct client_resource *r = p; struct client *client = data; r->release(client, r); client_put(client); return 0; }
int main(int argc, char *argv[]) { int confd; struct sockaddr_in server_addr; if(argc < 5) { printf("input format is :\nput [-h hostname] [-p portname] local_filename remote_filename\nget [-h hostname] [-p portname] remote_filename local_filename\n"); exit(1); } if(!strcmp(argv[1],"put"))//输出提示。 printf("%s hostname:%s,portname:%s,local_filename:%s,remote_filename:%s\n",argv[1],argv[2],argv[3],argv[4],argv[5]); else printf("%s hostname:%s,portname:%s,local_filename:%s,remote_filename:%s\n",argv[1],argv[2],argv[3],argv[5],argv[4]); server_addr.sin_family = PF_INET;//PF_INET(协议族) server_addr.sin_addr.s_addr = inet_addr(argv[2]);//主机字节顺序转换成网络字节顺序 server_addr.sin_port = htons(atoi(argv[3]));//该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型 bzero(&server_addr.sin_zero,8); //sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节 if ((confd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket fail\n"); exit(1); } if (connect(confd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("connect fail"); exit(1); } if (!strcmp(argv[1], "put")) { client_put(confd,argv[4],argv[5]); } else if (!strcmp(argv[1], "get")) { client_get(confd,argv[5],argv[4]); } else { printf("input format error\n"); } close(confd);//关闭连接 return 0; }
int main (int argc, char **argv) { int sock, len2, len; char opcode, filename[196], mode[12] = "octet"; // default is octet struct hostent *host; struct sockaddr_in server; char* host_addr = "127.0.0.1"; FILE *fp; if (argc < 2) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } argv++; argc--; if (strcmp(argv[0], "-h") == 0) { if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } host_addr = argv[1]; argv+=2; argc-=2; } if (strcmp(argv[0], "-P")==0){ if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } port = atoi(argv[1]); argv+=2; argc-=2; } if (strcmp(argv[0], "-g")==0){ if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } strncpy (filename, argv[1], sizeof (filename) - 1); opcode = RRQ; argv+=2; argc-=2; } else if (strcmp(argv[0], "-p")==0){ if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } strncpy (filename, argv[1], sizeof (filename) - 1); opcode = WRQ; argv+=2; argc-=2; } else if (strcmp(argv[0], "-n")==0){ strncpy (mode, "netascii", sizeof (mode) - 1); printf ("Client: The mode is set to netascii\n"); } else{ printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return (0); } printf("Client: server ip address: %s and port: %d \n", host_addr, port); if (!(host = gethostbyname (host_addr))) { perror ("could not obtain host address as"); exit (2); } printf("Client: Opening file: %s in %s mode \n", filename, (opcode == WRQ ? "Read": "Write") ); if(opcode == WRQ) fp = fopen (filename, "r"); else if(opcode == RRQ) fp = fopen (filename, "w"); if (fp == NULL) { printf ("Client: file could not be opened: file not found or permission denied\n"); return 0; } fclose (fp); /*Create the socket, a -1 will show us an error */ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("Client: socket"); return 0; } // bind to an arbitrary return address // because this is the client side, we don't care about the // address since no application will connect here // INADDR_ANY is the IP address and 0 is the socket // htonl converts a long integer (e.g. address) to a network // representation (agreed-upon byte ordering bzero(&server, sizeof (server)); server.sin_family = AF_INET; memcpy (&server.sin_addr, host->h_addr, host->h_length); // server.sin_addr.s_addr = htonl (INADDR_ANY); server.sin_port = htons (port); len2 = sizeof(server); memset(buf, 0, 512); // creates RRQ packet len = request_packet(opcode, filename, mode, buf); if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, len2) != len) { perror("Client: sendto has returend an error"); exit(-1); } printf("Client: %s packet sent\n", (opcode==1 ? "RRQ":"WRQ")); switch (opcode) { case RRQ: client_get(filename, server, mode, sock); break; case WRQ: client_put(filename, server, mode, sock); break; default: printf("Invalid opcode. Packet discarded."); } close(sock); return 1; }
static void schedule_iso_resource(struct iso_resource *r) { client_get(r->client); if (!schedule_delayed_work(&r->work, 0)) client_put(r->client); }
static void iso_resource_work(struct work_struct *work) { struct iso_resource_event *e; struct iso_resource *r = container_of(work, struct iso_resource, work.work); struct client *client = r->client; int generation, channel, bandwidth, todo; bool skip, free, success; spin_lock_irq(&client->lock); generation = client->device->generation; todo = r->todo; /* Allow 1000ms grace period for other reallocations. */ if (todo == ISO_RES_ALLOC && time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3))) client_get(client); skip = true; } else { /* We could be called twice within the same generation. */ skip = todo == ISO_RES_REALLOC && r->generation == generation; } free = todo == ISO_RES_DEALLOC || todo == ISO_RES_ALLOC_ONCE || todo == ISO_RES_DEALLOC_ONCE; r->generation = generation; spin_unlock_irq(&client->lock); if (skip) goto out; bandwidth = r->bandwidth; fw_iso_resource_manage(client->device->card, generation, r->channels, &channel, &bandwidth, todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC || todo == ISO_RES_ALLOC_ONCE, r->transaction_data); /* * Is this generation outdated already? As long as this resource sticks * in the idr, it will be scheduled again for a newer generation or at * shutdown. */ if (channel == -EAGAIN && (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC)) goto out; success = channel >= 0 || bandwidth > 0; spin_lock_irq(&client->lock); /* * Transit from allocation to reallocation, except if the client * requested deallocation in the meantime. */ if (r->todo == ISO_RES_ALLOC) r->todo = ISO_RES_REALLOC; /* * Allocation or reallocation failure? Pull this resource out of the * idr and prepare for deletion, unless the client is shutting down. */ if (r->todo == ISO_RES_REALLOC && !success && !client->in_shutdown && idr_find(&client->resource_idr, r->resource.handle)) { idr_remove(&client->resource_idr, r->resource.handle); client_put(client); free = true; } spin_unlock_irq(&client->lock); if (todo == ISO_RES_ALLOC && channel >= 0) r->channels = 1ULL << channel; if (todo == ISO_RES_REALLOC && success) goto out; if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) { e = r->e_alloc; r->e_alloc = NULL; } else { e = r->e_dealloc; r->e_dealloc = NULL; } e->resource.handle = r->resource.handle; e->resource.channel = channel; e->resource.bandwidth = bandwidth; queue_event(client, &e->event, &e->resource, sizeof(e->resource), NULL, 0); if (free) { cancel_delayed_work(&r->work); kfree(r->e_alloc); kfree(r->e_dealloc); kfree(r); } out: client_put(client); }