/** * 好友发送个性签名. */ void UdpData::SomeoneSendSign() { PalInfo *pal; char *sign; if (!(pal = cthrd.GetPalFromList(ipv4))) return; /* 若好友不兼容iptux协议,则需转码 */ if (!FLAG_ISSET(pal->flags, 0)) ConvertEncode(pal->encode); /* 对编码作适当调整 */ if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) { g_free(pal->encode); pal->encode = g_strdup(encode ? encode : "utf-8"); } /* 更新 */ if ( (sign = ipmsg_get_attach(buf, ':', 5))) { g_free(pal->sign); pal->sign = sign; gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); cthrd.UpdatePalToList(ipv4); pthread_mutex_unlock(cthrd.GetMutex()); mwin.UpdateItemToPaltree(ipv4); gdk_threads_leave(); } }
/** * 更新好友信息数据. * @param pal 好友数据 */ void UdpData::UpdatePalInfo(PalInfo *pal) { g_free(pal->segdes); pal->segdes = progdt.FindNetSegDescription(ipv4); g_free(pal->version); if (!(pal->version = iptux_get_section_string(buf, ':', 0))) pal->version = g_strdup("?"); g_free(pal->user); if (!(pal->user = iptux_get_section_string(buf, ':', 2))) pal->user = g_strdup("???"); g_free(pal->host); if (!(pal->host = iptux_get_section_string(buf, ':', 3))) pal->host = g_strdup("???"); if (!FLAG_ISSET(pal->flags, 2)) { g_free(pal->name); if (!(pal->name = ipmsg_get_attach(buf, ':', 5))) pal->name = g_strdup(_("mysterious")); g_free(pal->group); pal->group = GetPalGroup(); g_free(pal->iconfile); if (!(pal->iconfile = GetPalIcon())) pal->iconfile = g_strdup(progdt.palicon); FLAG_CLR(pal->flags, 0); g_free(pal->encode); if ( (pal->encode = GetPalEncode())) FLAG_SET(pal->flags, 0); else pal->encode = g_strdup(encode ? encode : "utf-8"); } FLAG_SET(pal->flags, 1); pal->packetn = 0; pal->rpacketn = 0; }
/** * 好友上线. */ void UdpData::SomeoneEntry() { Command cmd; pthread_t pid; PalInfo *pal; /* 转换缓冲区数据编码 */ ConvertEncode(progdt.encode); /* 加入或更新好友列表 */ gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); if ( (pal = cthrd.GetPalFromList(ipv4))) { UpdatePalInfo(pal); cthrd.UpdatePalToList(ipv4); } else { pal = CreatePalInfo(); cthrd.AttachPalToList(pal); } pthread_mutex_unlock(cthrd.GetMutex()); if (mwin.PaltreeContainItem(ipv4)) mwin.UpdateItemToPaltree(ipv4); else mwin.AttachItemToPaltree(ipv4); gdk_threads_leave(); /* 通知好友本大爷在线 */ cmd.SendAnsentry(cthrd.UdpSockQuote(), pal); if (FLAG_ISSET(pal->flags, 0)) { pthread_create(&pid, NULL, ThreadFunc(CoreThread::SendFeatureData), pal); pthread_detach(pid); } }
extern int attrlayer_flush(int flags) { static t_elist *curr = &loadedlist; static t_elist *next = NULL; t_attrgroup *attrgroup; unsigned int fcount; unsigned int tcount; fcount = tcount = 0; if (curr == &loadedlist || FLAG_ISSET(flags, FS_ALL)) { curr = elist_next(&loadedlist); next = elist_next(curr); } /* elist_for_each_safe splitted into separate startup for userstep function */ for (; curr != &loadedlist; curr = next, next = elist_next(curr)) { if (!FLAG_ISSET(flags, FS_ALL) && tcount >= prefs_get_user_step()) break; attrgroup = elist_entry(curr, t_attrgroup, loadedlist); switch (attrgroup_flush(attrgroup, flags)) { case 0: /* stop on the first account not flushed (ie accessed too early) */ goto loopout; case 1: fcount++; break; case -1: eventlog(eventlog_level_error, __FUNCTION__, "could not flush account"); break; default: break; } tcount++; } loopout: if (fcount > 0) eventlog(eventlog_level_debug, __FUNCTION__, "flushed %u user accounts", fcount); if (!FLAG_ISSET(flags, FS_ALL) && curr != &loadedlist) return 1; return 0; }
/* * Get NVMeD (NVMeDirect wide) features */ int nvmed_feature_get(NVMED* nvmed, int feature) { switch(feature) { case NVMED_CACHE_LAZY_INIT: return FLAG_ISSET(nvmed, NVMED_CACHE_LAZY_INIT); break; case NVMED_CACHE_SIZE: return nvmed->num_cache_size; }; return 0; }
/** * 将好友信息数据写入指定的缓冲区. * @param buffer text-buffer * @param pal class PalInfo */ void DialogPeer::FillPalInfoToBuffer(GtkTextBuffer *buffer, PalInfo *pal) { char buf[MAX_BUFLEN], ipstr[INET_ADDRSTRLEN]; GdkPixbuf *pixbuf; GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); snprintf(buf, MAX_BUFLEN, _("Version: %s\n"), pal->version); gtk_text_buffer_insert(buffer, &iter, buf, -1); if (pal->group && *pal->group != '\0') snprintf(buf, MAX_BUFLEN, _("Nickname: %s@%s\n"), pal->name, pal->group); else snprintf(buf, MAX_BUFLEN, _("Nickname: %s\n"), pal->name); gtk_text_buffer_insert(buffer, &iter, buf, -1); snprintf(buf, MAX_BUFLEN, _("User: %s\n"), pal->user); gtk_text_buffer_insert(buffer, &iter, buf, -1); snprintf(buf, MAX_BUFLEN, _("Host: %s\n"), pal->host); gtk_text_buffer_insert(buffer, &iter, buf, -1); inet_ntop(AF_INET, &pal->ipv4, ipstr, INET_ADDRSTRLEN); if (pal->segdes && *pal->segdes != '\0') snprintf(buf, MAX_BUFLEN, _("Address: %s(%s)\n"), pal->segdes, ipstr); else snprintf(buf, MAX_BUFLEN, _("Address: %s\n"), ipstr); gtk_text_buffer_insert(buffer, &iter, buf, -1); if (!FLAG_ISSET(pal->flags, 0)) snprintf(buf, MAX_BUFLEN, _("Compatibility: Microsoft\n")); else snprintf(buf, MAX_BUFLEN, _("Compatibility: GNU/Linux\n")); gtk_text_buffer_insert(buffer, &iter, buf, -1); snprintf(buf, MAX_BUFLEN, _("System coding: %s\n"), pal->encode); gtk_text_buffer_insert(buffer, &iter, buf, -1); if (pal->sign && *pal->sign != '\0') { gtk_text_buffer_insert(buffer, &iter, _("Signature:\n"), -1); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, pal->sign, -1, "sign-words", NULL); } if (pal->photo && *pal->photo != '\0' && (pixbuf = gdk_pixbuf_new_from_file(pal->photo, NULL))) { gtk_text_buffer_insert(buffer, &iter, _("\nPhoto:\n"), -1); //TODO 缩放多少才合适 pixbuf_shrink_scale_1(&pixbuf, 200, -1); gtk_text_buffer_insert_pixbuf(buffer, &iter, pixbuf); g_object_unref(pixbuf); } }
/** * 某好友请求本计算机的共享文件. * @param pal class PalInfo */ void UdpData::ThreadAskSharedFile(PalInfo *pal) { SendFile sfile; bool permit; if (FLAG_ISSET(progdt.flags, 0)) { gdk_threads_enter(); permit = pop_request_shared_file(pal); gdk_threads_leave(); if (permit) sfile.SendSharedInfoEntry(pal); } else sfile.SendSharedInfoEntry(pal); }
int syscmd_file_can_read(char *filename) { struct stat stat_buf; #define FLAG_ISSET(V,F) (((V) & (F)) == (F)) if (!stat(filename, &stat_buf)) { if (FLAG_ISSET(stat_buf.st_mode, S_IRUSR)) { return 1; } } return 0; }
/** * 分派UDP数据到相应的函数去进行处理. */ void UdpData::DispatchUdpData() { uint32_t commandno; /* 如果开启了黑名单处理功能,且此地址正好被列入了黑名单 */ /* 嘿嘿,那就不要怪偶心狠手辣了 */ if (FLAG_ISSET(progdt.flags, 1) && cthrd.BlacklistContainItem(ipv4)) return; /* 决定消息去向 */ commandno = iptux_get_dec_number(buf, ':', 4); switch (GET_MODE(commandno)) { case IPMSG_BR_ENTRY: SomeoneEntry(); break; case IPMSG_BR_EXIT: SomeoneExit(); break; case IPMSG_ANSENTRY: SomeoneAnsentry(); break; case IPMSG_BR_ABSENCE: SomeoneAbsence(); break; case IPMSG_SENDMSG: SomeoneSendmsg(); break; case IPMSG_RECVMSG: SomeoneRecvmsg(); break; case IPTUX_ASKSHARED: SomeoneAskShared(); break; case IPTUX_SENDICON: SomeoneSendIcon(); break; case IPTUX_SENDSIGN: SomeoneSendSign(); break; case IPTUX_SENDMSG: SomeoneBcstmsg(); break; default: break; } }
/** * 播放音频文件. * @param file 音频文件 * @note 如果时间间隔过短,系统将会忽略后一个请求. */ void SoundSystem::Playing(const char *file) { GstElement *pipeline, *filesrc; struct timeval time; gettimeofday(&time, NULL); if (!FLAG_ISSET(progdt.sndfgs, 0) || (difftimeval(time, timestamp) < 0.1)) return; if (persist) EosMessageOccur(this); persist = true; filesrc = GST_ELEMENT(g_datalist_get_data(&eltset, "filesrc-element")); g_object_set(filesrc, "location", file, NULL); pipeline = GST_ELEMENT(g_datalist_get_data(&eltset, "pipeline-element")); gst_element_set_state(pipeline, GST_STATE_PLAYING); timestamp = time; }
/** * Pack filehandles * @param buf Buffer * @return If buf is NULL return needed size */ size_t _fs_pack_filehandles(pack_t buf) { struct filelist_item *file; struct fslist_item *fs; size_t i; if (buf==NULL) { // Prepare filesystems size_t size = sizeof(size_t)+llist_size(fslist)*sizeof(int)*2; // id, pid for (i=0;(fs = llist_get(fslist,i));i++) size += strlen(fs->mountpoint_str)+1; // mountpoint // Prepare files size += sizeof(size_t)+llist_size(filelist)*sizeof(int)*8; // fh, fs_fh, stfl, fdfl, shmid, type, mode for (i=0;(file = llist_get(filelist,i));i++) size += strlen(file->path)+1; // path return size; } else { // Pack filesystems packi(buf,llist_size(fslist)); for (i=0;(fs = llist_get(fslist,i));i++) { packi(buf,fs->id); packi(buf,fs->pid); packstr(buf,fs->mountpoint_str); } // Pack files packi(buf,llist_size(filelist)); for (i=0;(file = llist_get(filelist,i));i++) { if (file->type!=FL_DIR && !FLAG_ISSET(file->fdfl,FD_CLOEXEC)) { packi(buf,file->fh); packi(buf,file->fs_fh); packi(buf,file->shmid); packi(buf,file->type); packi(buf,file->mode); packi(buf,file->stfl); packi(buf,file->fdfl); packi(buf,file->fs->id); packstr(buf,file->path); } } return 0; } }
/** * 好友发送头像数据. */ void UdpData::SomeoneSendIcon() { PalInfo *pal; char *iconfile; if (!(pal = cthrd.GetPalFromList(ipv4)) || FLAG_ISSET(pal->flags, 2)) return; /* 接收并更新数据 */ if ( (iconfile = RecvPalIcon())) { g_free(pal->iconfile); pal->iconfile = iconfile; gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); cthrd.UpdatePalToList(ipv4); pthread_mutex_unlock(cthrd.GetMutex()); mwin.UpdateItemToPaltree(ipv4); gdk_threads_leave(); } }
/* * Destroy MQ Handle */ int nvmed_handle_destroy_mq(NVMED_HANDLE* nvmed_handle) { int i; if(nvmed_handle == NULL) return -NVMED_NOENTRY; if(!FLAG_ISSET(nvmed_handle, HANDLE_MQ)) { nvmed_printf("%s: failed to destroy MQ - not MQ\n", HtoD(nvmed_handle)->ns_path); return -NVMED_FAULT; } for(i=1; i<nvmed_handle->num_mq; i++) { pthread_spin_lock(&nvmed_handle->queue_mq[i]->mngt_lock); nvmed_handle->queue_mq[i]->numHandle--; pthread_spin_unlock(&nvmed_handle->queue_mq[i]->mngt_lock); } free(nvmed_handle->queue_mq); return nvmed_handle_destroy(nvmed_handle); }
/** * 确保好友一定在线. * @return 好友数据 */ PalInfo *UdpData::AssertPalOnline() { PalInfo *pal; if ( (pal = cthrd.GetPalFromList(ipv4))) { /* 既然好友不在线,那么他自然不在列表中 */ if (!FLAG_ISSET(pal->flags, 1)) { FLAG_SET(pal->flags, 1); gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); cthrd.UpdatePalToList(ipv4); pthread_mutex_unlock(cthrd.GetMutex()); mwin.AttachItemToPaltree(ipv4); gdk_threads_leave(); } } else { SomeoneLost(); pal = cthrd.GetPalFromList(ipv4); } return pal; }
/** * 好友在线. */ void UdpData::SomeoneAnsentry() { Command cmd; pthread_t pid; PalInfo *pal; const char *ptr; /* 若好友不兼容iptux协议,则需转码 */ ptr = iptux_skip_string(buf, size, 3); if (!ptr || *ptr == '\0') ConvertEncode(progdt.encode); /* 加入或更新好友列表 */ gdk_threads_enter(); pthread_mutex_lock(cthrd.GetMutex()); if ( (pal = cthrd.GetPalFromList(ipv4))) { UpdatePalInfo(pal); cthrd.UpdatePalToList(ipv4); } else { pal = CreatePalInfo(); cthrd.AttachPalToList(pal); } pthread_mutex_unlock(cthrd.GetMutex()); if (mwin.PaltreeContainItem(ipv4)) mwin.UpdateItemToPaltree(ipv4); else mwin.AttachItemToPaltree(ipv4); gdk_threads_leave(); /* 更新本大爷的数据信息 */ if (FLAG_ISSET(pal->flags, 0)) { pthread_create(&pid, NULL, ThreadFunc(CoreThread::SendFeatureData), pal); pthread_detach(pid); } else if (strcasecmp(progdt.encode, pal->encode) != 0) cmd.SendAnsentry(cthrd.UdpSockQuote(), pal); }
/** * 好友广播消息. */ void UdpData::SomeoneBcstmsg() { GroupInfo *grpinf; PalInfo *pal; uint32_t commandno, packetno; char *text; /* 如果对方兼容iptux协议,则无须再转换编码 */ pal = cthrd.GetPalFromList(ipv4); if (!pal || !FLAG_ISSET(pal->flags, 0)) ConvertEncode(pal ? pal->encode : progdt.encode); /* 确保好友在线,并对编码作出适当调整 */ pal = AssertPalOnline(); if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) { g_free(pal->encode); pal->encode = g_strdup(encode ? encode : "utf-8"); } /* 检查此消息是否过时 */ packetno = iptux_get_dec_number(buf, ':', 1); if (packetno <= pal->packetn) return; pal->packetn = packetno; /* 插入消息&在消息队列中注册 */ text = ipmsg_get_attach(buf, ':', 5); if (text && *text != '\0') { commandno = iptux_get_dec_number(buf, ':', 4); /*/* 插入消息 */ switch (GET_OPT(commandno)) { case IPTUX_BROADCASTOPT: InsertMessage(pal, GROUP_BELONG_TYPE_BROADCAST, text); break; case IPTUX_GROUPOPT: InsertMessage(pal, GROUP_BELONG_TYPE_GROUP, text); break; case IPTUX_SEGMENTOPT: InsertMessage(pal, GROUP_BELONG_TYPE_SEGMENT, text); break; case IPTUX_REGULAROPT: default: InsertMessage(pal, GROUP_BELONG_TYPE_REGULAR, text); break; } /*/* 注册消息 */ pthread_mutex_lock(cthrd.GetMutex()); switch (GET_OPT(commandno)) { case IPTUX_BROADCASTOPT: grpinf = cthrd.GetPalBroadcastItem(pal); break; case IPTUX_GROUPOPT: grpinf = cthrd.GetPalGroupItem(pal); break; case IPTUX_SEGMENTOPT: grpinf = cthrd.GetPalSegmentItem(pal); break; case IPTUX_REGULAROPT: default: grpinf = cthrd.GetPalRegularItem(pal); break; } if (!grpinf->dialog && !cthrd.MsglineContainItem(grpinf)) cthrd.PushItemToMsgline(grpinf); pthread_mutex_unlock(cthrd.GetMutex()); } g_free(text); /* 播放提示音 */ if (FLAG_ISSET(progdt.sndfgs, 1)) sndsys.Playing(progdt.msgtip); }
/** * 好友发送消息. * */ void UdpData::SomeoneSendmsg() { GroupInfo *grpinf; PalInfo *pal; Command cmd; uint32_t commandno, packetno; char *text; pthread_t pid; DialogPeer *dlgpr; GtkWidget *window; /* 如果对方兼容iptux协议,则无须再转换编码 */ pal = cthrd.GetPalFromList(ipv4); if (!pal || !FLAG_ISSET(pal->flags, 0)) ConvertEncode(pal ? pal->encode : progdt.encode); /* 确保好友在线,并对编码作出适当调整 */ pal = AssertPalOnline(); if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) { g_free(pal->encode); pal->encode = g_strdup(encode ? encode : "utf-8"); } /* 回复好友并检查此消息是否过时 */ commandno = iptux_get_dec_number(buf, ':', 4); packetno = iptux_get_dec_number(buf, ':', 1); if (commandno & IPMSG_SENDCHECKOPT) cmd.SendReply(cthrd.UdpSockQuote(), pal, packetno); if (packetno <= pal->packetn) return; pal->packetn = packetno; /* 插入消息&在消息队列中注册 */ text = ipmsg_get_attach(buf, ':', 5); if (text && *text != '\0') { /*/* 插入消息 */ // if ((commandno & IPMSG_BROADCASTOPT) || (commandno & IPMSG_MULTICASTOPT)) // InsertMessage(pal, GROUP_BELONG_TYPE_BROADCAST, text); // else InsertMessage(pal, GROUP_BELONG_TYPE_REGULAR, text); } g_free(text); /*/* 注册消息 */ pthread_mutex_lock(cthrd.GetMutex()); // if ((commandno & IPMSG_BROADCASTOPT) || (commandno & IPMSG_MULTICASTOPT)) // grpinf = cthrd.GetPalBroadcastItem(pal); // else grpinf = cthrd.GetPalRegularItem(pal); if (!grpinf->dialog && !cthrd.MsglineContainItem(grpinf)) cthrd.PushItemToMsgline(grpinf); pthread_mutex_unlock(cthrd.GetMutex()); /* 标记位处理 先处理底层数据,后面显示窗口*/ if (commandno & IPMSG_FILEATTACHOPT) { if ((commandno & IPTUX_SHAREDOPT) && (commandno & IPTUX_PASSWDOPT)) { pthread_create(&pid, NULL, ThreadFunc(ThreadAskSharedPasswd), pal); pthread_detach(pid); } else RecvPalFile(); } window = GTK_WIDGET(grpinf->dialog); //这里不知道为什么运行时一直会提示window不是object dlgpr = (DialogPeer *)(g_object_get_data(G_OBJECT(window),"dialog")); if(grpinf->dialog) dlgpr->ShowDialogPeer(dlgpr); /* 是否直接弹出聊天窗口 */ if (FLAG_ISSET(progdt.flags, 7)) { gdk_threads_enter(); if (!(grpinf->dialog)) { // switch (grpinf->type) { // case GROUP_BELONG_TYPE_REGULAR: DialogPeer::PeerDialogEntry(grpinf); // break; // case GROUP_BELONG_TYPE_SEGMENT: // case GROUP_BELONG_TYPE_GROUP: // case GROUP_BELONG_TYPE_BROADCAST: // DialogGroup::GroupDialogEntry(grpinf); // default: // break; // } } else { gtk_window_present(GTK_WINDOW(grpinf->dialog)); } gdk_threads_leave(); } /* 播放提示音 */ if (FLAG_ISSET(progdt.sndfgs, 1)) sndsys.Playing(progdt.msgtip); }
/* Get CACHE from free list or evict */ NVMED_CACHE* nvmed_get_cache(NVMED_HANDLE* nvmed_handle) { NVMED* nvmed = HtoD(nvmed_handle); NVMED_CACHE *cache = nvmed->free_head.tqh_first; NVMED_CACHE *__cache; NVMED_CACHE *ret_cache; int i; unsigned int start_lpaddr, end_lpaddr; TAILQ_HEAD(cache_list, nvmed_cache) temp_head; pthread_rwlock_wrlock(&nvmed->cache_radix_lock); pthread_spin_lock(&nvmed->cache_list_lock); if(cache==NULL) { //HEAD -> LRU, //TAIL -> MRU //EVICT - LRU cache = nvmed->lru_head.tqh_first; if(!FLAG_ISSET(cache, CACHE_DIRTY)) { TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list); LIST_REMOVE(cache, handle_cache_list); radix_tree_delete(&nvmed->cache_root, cache->lpaddr); FLAG_SET_FORCE(cache, 0); ret_cache = cache; } else { TAILQ_INIT(&temp_head); while(FLAG_ISSET_SYNC(cache, CACHE_LOCKED) || cache->ref != 0) { usleep(1); } start_lpaddr = cache->lpaddr; end_lpaddr = cache->lpaddr; __cache = cache->cache_list.tqe_next; TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list); radix_tree_delete(&nvmed->cache_root, cache->lpaddr); TAILQ_INSERT_HEAD(&temp_head, cache, cache_list); for(i=1; i<NVMED_CACHE_FORCE_EVICT_MAX; i++) { cache = __cache; if(FLAG_ISSET_SYNC(cache, CACHE_LOCKED)) break; if(!FLAG_ISSET(cache, CACHE_DIRTY)) break; if(start_lpaddr != 0 && cache->lpaddr == start_lpaddr-1 ) { //front_merge start_lpaddr--; __cache = cache->cache_list.tqe_next; TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list); radix_tree_delete(&nvmed->cache_root, cache->lpaddr); TAILQ_INSERT_HEAD(&temp_head, cache, cache_list); continue; } else if(cache->lpaddr == end_lpaddr+1) { //back_merge end_lpaddr++; __cache = cache->cache_list.tqe_next; TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list); radix_tree_delete(&nvmed->cache_root, cache->lpaddr); TAILQ_INSERT_TAIL(&temp_head, cache, cache_list); continue; } else { break; } } if(FLAG_ISSET(cache, CACHE_DIRTY)) nvmed_cache_io_rw(nvmed_handle, nvme_cmd_write, temp_head.tqh_first, start_lpaddr * PAGE_SIZE, (end_lpaddr - start_lpaddr) * PAGE_SIZE, HANDLE_SYNC_IO); cache = temp_head.tqh_first; FLAG_SET_FORCE(cache, 0); ret_cache = cache; TAILQ_REMOVE(&temp_head, cache, cache_list); LIST_REMOVE(cache, handle_cache_list); while(temp_head.tqh_first != NULL) { TAILQ_REMOVE(&temp_head, temp_head.tqh_first, cache_list); TAILQ_INSERT_HEAD(&nvmed->free_head, temp_head.tqh_first, cache_list); nvmed->num_cache_usage--; } } } else { // Remove From Free Queue TAILQ_REMOVE(&nvmed->free_head, cache, cache_list); FLAG_UNSET_SYNC(cache, CACHE_FREE); if(FLAG_ISSET(cache, CACHE_UNINIT)) { memset(cache->ptr, 0, PAGE_SIZE); virt_to_phys(nvmed, cache->ptr, &cache->paddr, 4096); FLAG_UNSET_SYNC(cache, CACHE_UNINIT); } ret_cache = cache; } INIT_SYNC(ret_cache->ref); pthread_spin_unlock(&nvmed->cache_list_lock); pthread_rwlock_unlock(&nvmed->cache_radix_lock); return ret_cache; }
/* * Get Handle Features */ int nvmed_handle_feature_get(NVMED_HANDLE* nvmed_handle, int feature) { return FLAG_ISSET(nvmed_handle, feature); }
/* * Make I/O request from NVMeDirect Cache */ ssize_t nvmed_cache_io_rw(NVMED_HANDLE* nvmed_handle, u8 opcode, NVMED_CACHE *__cache, unsigned long start_lba, unsigned int len, int __flag) { NVMED_QUEUE* nvmed_queue; NVMED* nvmed; NVMED_CACHE* cache; int num_cache; int flag; ssize_t remain = 0; ssize_t io_size, io = 0, total_io = 0; unsigned long io_lba; u64 prp1, prp2; void* prp2_addr; if(len % PAGE_SIZE) return 0; if(__flag != 0) flag = __flag; else flag = nvmed_handle->flags; if(FLAG_ISSET(nvmed_handle, HANDLE_MQ)) { nvmed_queue = nvmed_handle->mq_get_queue(nvmed_handle, opcode, start_lba, len); if(nvmed_queue == NULL) return 0; } else { nvmed_queue = HtoQ(nvmed_handle); } nvmed = nvmed_queue->nvmed; remain = len; cache = __cache; num_cache = len / PAGE_SIZE; while(num_cache-- > 0) { FLAG_SET_SYNC(cache, CACHE_LOCKED); cache = cache->cache_list.tqe_next; } cache = __cache; while(remain > 0) { if(remain > nvmed->dev_info->max_hw_sectors * 512 ) io_size = nvmed->dev_info->max_hw_sectors * 512; else io_size = remain; io_lba = total_io + start_lba; num_cache = io_size / PAGE_SIZE; make_prp_list_from_cache(nvmed_handle, cache, num_cache, &prp1, &prp2, &prp2_addr); io = nvmed_io(nvmed_handle, opcode, prp1, prp2, prp2_addr, cache, io_lba, io_size, flag, NULL); if(io <= 0) break; remain -= io; total_io += io; io_lba += io; while(num_cache-- > 0) cache = cache->cache_list.tqe_next; } return total_io; }