diff --git a/frameworks/native/cloud_file_kit_inner/src/cloud_asset_read_session.cpp b/frameworks/native/cloud_file_kit_inner/src/cloud_asset_read_session.cpp index 8008d28d988d674197c7fa1446a5489aea60863d..e7c688905a2b3246b12b671ccb6e0b6e9e808f72 100644 --- a/frameworks/native/cloud_file_kit_inner/src/cloud_asset_read_session.cpp +++ b/frameworks/native/cloud_file_kit_inner/src/cloud_asset_read_session.cpp @@ -33,7 +33,11 @@ CloudError CloudAssetReadSession::InitSession() return CloudError::CK_NO_ERROR; } -int64_t CloudAssetReadSession::PRead(int64_t offset, int64_t size, char *buffer, CloudError &error) +int64_t CloudAssetReadSession::PRead(int64_t offset, + int64_t size, + char *buffer, + CloudError &error, + const std::string appId = "default ") { return E_OK; } @@ -43,14 +47,14 @@ bool CloudAssetReadSession::Close(bool needRemain) return true; } -bool CloudAssetReadSession::HasCache(int64_t offset, int64_t readSize) +void CloudAssetReadSession::SentPrepareTraceId(std::string prepareTraceId) { - return true; + return; } -void CloudAssetReadSession::SentPrepareTraceId(std::string prepareTraceId) +bool CloudAssetReadSession::Catch(CloudError &error, uint32_t catchTimeOutPara) { - return; + return true; } void CloudAssetReadSession::SetPrepareTraceId(std::string prepareTraceId) diff --git a/interfaces/inner_api/native/cloud_file_kit_inner/cloud_asset_read_session.h b/interfaces/inner_api/native/cloud_file_kit_inner/cloud_asset_read_session.h index dc6e13b61e3b02455a5203d8a196e337809dfc68..a9e9944b738020f778dbc6d03fb6ad4baca44f2e 100644 --- a/interfaces/inner_api/native/cloud_file_kit_inner/cloud_asset_read_session.h +++ b/interfaces/inner_api/native/cloud_file_kit_inner/cloud_asset_read_session.h @@ -29,10 +29,14 @@ public: virtual ~CloudAssetReadSession() = default; virtual CloudError InitSession(); - virtual int64_t PRead(int64_t offset, int64_t size, char *buffer, CloudError &error); + virtual int64_t PRead(int64_t offset, + int64_t size, + char *buffer, + CloudError &error, + const std::string appId = "default"); virtual bool Close(bool needRemain = false); - virtual bool HasCache(int64_t offset, int64_t readSize); virtual void SentPrepareTraceId(std::string prepareTraceId); + virtual bool Catch(CloudError &error, uint32_t catchTimeOutPara); void SetPrepareTraceId(std::string prepareTraceId); std::string GetPrepareTraceId(); diff --git a/services/cloudfiledaemon.cfg b/services/cloudfiledaemon.cfg index 50ea8aa4ed046dc137c452f90abe90db26233963..06906d7aaf39302c51ac2877512866bd3060271c 100644 --- a/services/cloudfiledaemon.cfg +++ b/services/cloudfiledaemon.cfg @@ -16,7 +16,8 @@ "ohos.permission.USE_CLOUD_DRIVE_SERVICE", "ohos.permission.READ_CLOUD_SYNC_CONFIG", "ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS", - "ohos.permission.GET_BUNDLE_INFO" + "ohos.permission.GET_BUNDLE_INFO", + "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED" ] }] } \ No newline at end of file diff --git a/services/cloudfiledaemon/src/fuse_manager/fuse_manager.cpp b/services/cloudfiledaemon/src/fuse_manager/fuse_manager.cpp index 119ec4e9845ad326d1e82e49453165fe1f8a7131..ec989778e9948ea6ae952f2d2a59f5d98d827047 100644 --- a/services/cloudfiledaemon/src/fuse_manager/fuse_manager.cpp +++ b/services/cloudfiledaemon/src/fuse_manager/fuse_manager.cpp @@ -91,7 +91,9 @@ static const unsigned int MAX_IDLE_THREADS = 6; static const unsigned int READ_CACHE_SLEEP = 10 * 1000; static const unsigned int CACHE_PAGE_NUM = 2; static const unsigned int HMDFS_IOC = 0xf2; +static const unsigned int MAX_APPID_LEN = 256; static const unsigned int FUSE_BUFFER_SIZE = 512 * 1024; +static const unsigned int CATCH_TIMEOUT_MS = 4 * 1000; static const std::chrono::seconds READ_TIMEOUT_S = 16s; static const std::chrono::seconds OPEN_TIMEOUT_S = 4s; #ifdef HICOLLIE_ENABLE @@ -102,6 +104,7 @@ static const unsigned int FORGET_TIMEOUT_S = 1; #define HMDFS_IOC_HAS_CACHE _IOW(HMDFS_IOC, 6, struct HmdfsHasCache) #define HMDFS_IOC_CANCEL_READ _IO(HMDFS_IOC, 8) #define HMDFS_IOC_RESET_READ _IO(HMDFS_IOC, 9) +#define HMDFS_IOC_SAVE_APPID _IOW(HMDFS_IOC, 10, struct HmdfsSaveAppId) PAGE_FLAG_TYPE PG_READAHEAD = 0x00000001; PAGE_FLAG_TYPE PG_UPTODATE = 0x00000002; PAGE_FLAG_TYPE PG_REFERENCED = 0x00000004; @@ -138,6 +141,7 @@ struct ReadSize { struct ReadArguments { size_t size{0}; + std::string appId {"default"}; off_t offset{0}; pid_t pid{0}; shared_ptr readResult{nullptr}; @@ -146,7 +150,8 @@ struct ReadArguments { shared_ptr cond{nullptr}; shared_ptr buf{nullptr}; - ReadArguments(size_t readSize, off_t readOffset, pid_t readPid) : size(readSize), offset(readOffset), pid(readPid) + ReadArguments(size_t readSize, std::string readAppId, off_t readOffset, pid_t readPid) : size(readSize), + appId(readAppId), offset(readOffset), pid(readPid) { readResult = make_shared(-1); readStatus = make_shared(READING); @@ -158,6 +163,12 @@ struct ReadArguments { } }; +struct CloudFdInfo { + std::string appId{"default"}; + size_t fdsan{UINT64_MAX}; + std::mutex modifyLock; +}; + struct CloudInode { shared_ptr mBase{nullptr}; string path; @@ -166,6 +177,7 @@ struct CloudInode { shared_ptr readSession{nullptr}; atomic sessionRefCount{0}; std::shared_mutex sessionLock; + std::shared_mutex readCloudFdMapLock; ffrt::mutex readLock; ffrt::mutex openLock; std::mutex readArgsLock; @@ -175,6 +187,7 @@ struct CloudInode { std::set> readArgsSet; /* process's read status for ioctl, true when canceled */ std::map readCtlMap; + std::map> CloudFdMap; std::unique_ptr cacheFileIndex{nullptr}; bool SetReadCacheFlag(int64_t index, PAGE_FLAG_TYPE flag) { @@ -222,16 +235,32 @@ struct HmdfsHasCache { int64_t readSize; }; +struct HmdfsSaveAppId { + char appId[MAX_APPID_LEN]; +}; + struct FuseData { int userId; + int fileId{0}; shared_ptr rootNode{nullptr}; /* store CloudInode by path */ map> inodeCache; std::shared_mutex cacheLock; + std::shared_mutex insertLock; shared_ptr database; struct fuse_session *se; }; +static shared_ptr FindKeyInCloudMap(shared_ptr cInode, uint64_t key) +{ + std::shared_lock lock(cInode->readCloudFdMapLock); + auto it = cInode->CloudFdMap.find(key); + if (it == cInode->CloudFdMap.end()) { + return nullptr; + } + return it->second; +} + static void InsertReadArgs(shared_ptr cInode, vector> readArgsList) { std::unique_lock lock(cInode->readArgsLock); @@ -675,7 +704,13 @@ static int CloudOpenOnLocal(struct FuseData *data, shared_ptr cInode return 0; } auto fdsan = new fdsan_fd(fd); - fi->fh = reinterpret_cast(fdsan); + auto cloudFdInfo = FindKeyInCloudFdMap(cInode, fi->fh); + if (cloudFdInfo == nullptr) { + LOGE("CloudFdMap is nullptr"); + return 0; + } + std::unique_lock lock(cloudFdInfo->modifyLock); + cloudFdInfo->fdsan = reinterpret_cast(fdsan); return 0; } @@ -720,6 +755,9 @@ static void DownloadThmOrLcd(shared_ptr cInode, shared_ptrInitSession(); + if (cInode->mBase->fileType != FILE_TYPE_CONTENT) { + session->Catch(*err, CATCH_TIMEOUT_MS); + } { unique_lock lck(cInode->openLock); *openFinish = true; @@ -847,7 +885,12 @@ static void HandleReopen(fuse_req_t req, struct FuseData *data, shared_ptrfh = reinterpret_cast(fdsan); + auto cloudFdInfo = FindKeyInCloudFdMap(cInode, fi->fh); + if (cloudFdInfo == nullptr) { + auto newCloudFdInfo = std::make_shared(); + cInode->CloudFdMap[fi->fh] = newCloudFdInfo; + } + cInode->CloudFdMap[fi->fh]->fdsan = reinterpret_cast(fdsan); } while (0); cInode->sessionRefCount++; @@ -933,14 +976,20 @@ static void CloudOpen(fuse_req_t req, fuse_ino_t ino, { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); struct FuseData *data = static_cast(fuse_req_userdata(req)); - fi->fh = UINT64_MAX; + { + unique_lock lck(data->insertLock); + data->fileId++; + } shared_ptr cInode = GetCloudInode(data, ino); + fi->fh = static_cast(data->fileId); if (!cInode) { fuse_reply_err(req, ENOMEM); CLOUD_FILE_FAULT_REPORT(CloudFileFaultInfo{PHOTOS_BUNDLE_NAME, FaultOperation::OPEN, FaultType::INODE_FILE, ENOMEM, "failed to get cloud inode"}); return; } + std::shared_lock lock(cInode->readCloudFdmapLock); + cInode->CloudFdMap[fi->fh] = std::make_shared(); CloudOpenHelper(req, ino, fi, data, cInode); } @@ -960,10 +1009,14 @@ static void CloudRelease(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info * GetAnonyString(cInode->path).c_str(), cInode->sessionRefCount.load()); wSesLock.lock(); cInode->sessionRefCount--; - if (fi->fh != UINT64_MAX) { - auto fdsan = reinterpret_cast(fi->fh); - delete fdsan; - fi->fh = UINT64_MAX; + auto cloudFdInfo = FindKeyInCloudFdMap(cInode, fi->fh); + if (cloudFdInfo != nullptr) { + if (cloudFdInfo->fdsan != UINT64_MAX) { + auto fdsan = reinterpret_cast(cInode->CloudFdMap[fi->fh]->fdsan); + delete fdsan; + std::unique_lock lock(cloudFdInfo->modifyLock); + cloudFdInfo->fdsan = UINT64_MAX; + } } if (cInode->sessionRefCount == 0) { if (cInode->mBase->fileType == FILE_TYPE_CONTENT && (!cInode->readSession->Close(false))) { @@ -1106,6 +1159,46 @@ static void ResetRead(fuse_req_t req, fuse_ino_t ino) fuse_reply_ioctl(req, 0, NULL, 0); } +static void SaveAppId(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, const void *inBuf) +{ + struct FuseData *data = static_cast(fuse_req_userdata(req)); + shared_ptr cInode = GetCloudInode(data, ino); + if (!cInode || !cInode->readSession) { + fuse_reply_err(req, ENOMEM); + CLOUD_FILE_FAULT_REPORT(CloudFileFaultInfo{PHOTOS_BUNDLE_NAME, FaultOperation::IOCTL, + FaultType::INODE_FILE, ENOMEM, "Failed to get cloud inode"}); + return; + } + + if (fi == nullptr) { + fuse_reply_err(req, EINVAL); + CLOUD_FILE_FAULT_REPORT(CloudFileFaultInfo{PHOTOS_BUNDLE_NAME, FaultOperation::IOCTL, + FaultType::INODE_FILE, EINVAL, "File info is null"}); + return; + } + + const struct HmdfsSaveAppId *ioctlData = reinterpret_cast(inBuf); + if (!ioctlData) { + fuse_reply_err(req, EINVAL); + CLOUD_FILE_FAULT_REPORT(CloudFileFaultInfo{PHOTOS_BUNDLE_NAME, FaultOperation::IOCTL, + FaultType::WARNING, EINVAL, "Invalid argument in ioctl"}); + return; + } + auto cloudFdInfo = FindKeyInCloudFdMap(cInode, fi->fh); + if (cloudFdInfo != nullptr) { + std::unique_lock lock(cloudFdInfo->modifyLock); + char appIdBuffer[sizeof(ioctlData->appId) + 1]; + auto ret = strncpy_s(appIdBuffer, sizeof(appIdBuffer), ioctlData->appId, sizeof(ioctlData->appId)); + if (ret != EOK) { + LOGE("Copy path failed"); + fuse_reply_err(req, EINVAL); + return; + } + cloudFdInfo->appId = appIdBuffer; + fuse_reply_ioctl(req, 0, NULL, 0); + } +} + static void CloudIoctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, struct fuse_file_info *fi, unsigned flags, const void *inBuf, size_t inBufsz, size_t outBufsz) { @@ -1119,6 +1212,9 @@ static void CloudIoctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, struc case HMDFS_IOC_RESET_READ: ResetRead(req, ino); break; + case HMDFS_IOC_SAVE_APPID: + SaveAppId(req, ino, fi, inBuf); + break; default: fuse_reply_err(req, ENOTTY); } @@ -1203,7 +1299,7 @@ static void CloudReadOnCloudFile(pid_t pid, } *readArgs->readResult = - readSession->PRead(readArgs->offset, readArgs->size, readArgs->buf.get(), *readArgs->ckError); + readSession->PRead(readArgs->offset, readArgs->size, readArgs->buf.get(), *readArgs->ckError, readArgs->appId); uint64_t endTime = UTCTimeMilliSeconds(); uint64_t readTime = (endTime > startTime) ? (endTime - startTime) : 0; @@ -1262,7 +1358,7 @@ static void CloudReadOnCacheFile(shared_ptr readArgs, LOGI("To do preread cloudfile path: %{public}s, size: %{public}zd, offset: %{public}ld*4M", GetAnonyString(cInode->path).c_str(), readArgs->size, static_cast(cacheIndex)); *readArgs->readResult = - readSession->PRead(readArgs->offset, readArgs->size, readArgs->buf.get(), *readArgs->ckError); + readSession->PRead(readArgs->offset, readArgs->size, readArgs->buf.get(), *readArgs->ckError, readArgs->appId); uint64_t endTime = UTCTimeMilliSeconds(); uint64_t readTime = (endTime > startTime) ? (endTime - startTime) : 0; @@ -1285,9 +1381,9 @@ static void CloudReadOnCacheFile(shared_ptr readArgs, } static void CloudReadOnLocalFile(fuse_req_t req, shared_ptr buf, size_t size, - off_t off, struct fuse_file_info *fi) + off_t off, uint64_t fd) { - auto fdsan = reinterpret_cast(fi->fh); + auto fdsan = reinterpret_cast(fd); auto readSize = pread(fdsan->get(), buf.get(), size, off); if (readSize < 0) { fuse_reply_err(req, errno); @@ -1487,6 +1583,7 @@ static bool DoCloudRead(fuse_req_t req, int flags, DoCloudReadParams params) return true; } + std::string appId = params.readArgsHead->appId; struct FuseData *data = static_cast(fuse_req_userdata(req)); for (uint32_t i = 1; i <= CACHE_PAGE_NUM; i++) { int64_t cacheIndex = static_cast( @@ -1494,7 +1591,7 @@ static bool DoCloudRead(fuse_req_t req, int flags, DoCloudReadParams params) if (IsVideoType(params.cInode->mBase->name) && params.cInode->cacheFileIndex.get()[cacheIndex] == HAS_CACHED) { continue; } - auto readArgsCache = make_shared(0, cacheIndex * MAX_READ_SIZE, pid); + auto readArgsCache = make_shared(0, appId, cacheIndex * MAX_READ_SIZE, pid); if (!readArgsCache) { LOGE("Init readArgsCache failed"); break; @@ -1557,19 +1654,26 @@ static void CloudRead(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, FaultType::FILE, ENOMEM, "buffer is null"}); return; } - if (fi->fh != UINT64_MAX) { - CloudReadOnLocalFile(req, buf, size, off, fi); - return; + std::string appId = "default"; + { + auto cloudFdInfo = FindKeyInCloudFdMap(cInode, fi->fh); + if (cloudFdInfo != nullptr) { + if (cloudFdInfo->fdsan != UINT64_MAX) { + CloudReadOnLocalFile(req, buf, size, off, cloudFdInfo->fdsan); + return; + } + appId = cloudFdInfo->appId; + } } ReadSlice readSlice; /* slice read request into 4M pages */ InitReadSlice(size, off, readSlice); /* init readArgs for current page, and next page if cross pages */ - auto readArgsHead = make_shared(readSlice.sizeHead, readSlice.offHead, pid); + auto readArgsHead = make_shared(readSlice.sizeHead, appId, readSlice.offHead, pid); shared_ptr readArgsTail = nullptr; if (readSlice.sizeTail > 0) { - readArgsTail = make_shared(readSlice.sizeTail, readSlice.offTail, pid); + readArgsTail = make_shared(readSlice.sizeTail, appId, readSlice.offTail, pid); } if (!DoCloudRead(req, fi->flags, {cInode, dkReadSession, readArgsHead, readArgsTail})) { return;