// PublishVNode status_t Volume::PublishVNode(Node *node) { status_t error = NodeAdded(node); if (error == B_OK) { error = publish_vnode(GetID(), node->GetID(), node); if (error != B_OK) NodeRemoved(node); } return error; }
static status_t fs_mount(fs_volume* _volume, const char* device, uint32 flags, const char* args, ino_t* _rootID) { bool allowJoliet = true; iso9660_volume* volume; // Check for a 'nojoliet' parm // all we check for is the existance of 'nojoliet' in the parms. if (args != NULL) { uint32 i; char* spot; char* buf = strdup(args); uint32 len = strlen(buf); // lower case the parms data for (i = 0; i < len + 1; i++) buf[i] = tolower(buf[i]); // look for nojoliet spot = strstr(buf, "nojoliet"); if (spot != NULL) allowJoliet = false; free(buf); } // Try and mount volume as an ISO volume. status_t result = ISOMount(device, O_RDONLY, &volume, allowJoliet); if (result == B_OK) { *_rootID = ISO_ROOTNODE_ID; _volume->private_volume = volume; _volume->ops = &gISO9660VolumeOps; volume->volume = _volume; volume->id = _volume->id; result = publish_vnode(_volume, *_rootID, &volume->rootDirRec, &gISO9660VnodeOps, volume->rootDirRec.attr.stat[FS_DATA_FORMAT].st_mode, 0); if (result != B_OK) { block_cache_delete(volume->fBlockCache, false); free(volume); result = B_ERROR; } } return result; }
// Mount status_t Volume::Mount(fs_volume *fsVolume, const char *path) { Unmount(); status_t error = (path ? B_OK : B_BAD_VALUE); fFSVolume = fsVolume; // load the settings if (error == B_OK) { fSettings = new(nothrow) Settings; if (fSettings) error = fSettings->SetTo(path); else error = B_NO_MEMORY; } // copy the device name if (error == B_OK) { fDeviceName = new(nothrow) char[strlen(path) + 1]; if (fDeviceName) strcpy(fDeviceName, path); else error = B_NO_MEMORY; } // open disk if (error == B_OK) { fDevice = open(path, O_RDONLY); if (fDevice < 0) SET_ERROR(error, errno); } // read and analyze super block if (error == B_OK) error = _ReadSuperBlock(); if (error == B_OK) UpdateName(fsVolume->partition); // create and init block cache if (error == B_OK) { fBlockCache = new(nothrow) BlockCache; if (fBlockCache) error = fBlockCache->Init(fDevice, CountBlocks(), GetBlockSize()); else error = B_NO_MEMORY; } // create the tree if (error == B_OK) { fTree = new(nothrow) Tree; if (!fTree) error = B_NO_MEMORY; } // get the root node and init the tree if (error == B_OK) { Block *rootBlock = NULL; error = fBlockCache->GetBlock(fSuperBlock->GetRootBlock(), &rootBlock); REPORT_ERROR(error); if (error == B_OK) { rootBlock->SetKind(Block::KIND_FORMATTED); error = fTree->Init(this, rootBlock->ToNode(), fSuperBlock->GetTreeHeight()); REPORT_ERROR(error); rootBlock->Put(); } } // get the root VNode (i.e. the root dir) if (error == B_OK) { fRootVNode = new(nothrow) VNode; if (fRootVNode) { error = FindVNode(REISERFS_ROOT_PARENT_OBJECTID, REISERFS_ROOT_OBJECTID, fRootVNode); REPORT_ERROR(error); if (error == B_OK) { error = publish_vnode(fFSVolume, fRootVNode->GetID(), fRootVNode, &gReiserFSVnodeOps, S_IFDIR, 0); } REPORT_ERROR(error); } else error = B_NO_MEMORY; } // init the hash function if (error == B_OK) _InitHashFunction(); // init the negative entry list if (error == B_OK) _InitNegativeEntries(); // cleanup on error if (error != B_OK) Unmount(); RETURN_ERROR(error); }
static status_t nfs4_mount(fs_volume* volume, const char* device, uint32 flags, const char* args, ino_t* _rootVnodeID) { TRACE("volume = %p, device = %s, flags = %" B_PRIu32 ", args = %s", volume, device, flags, args); status_t result; /* prepare idmapper server */ MutexLocker locker(gIdMapperLock); gIdMapper = new(std::nothrow) IdMap; if (gIdMapper == NULL) return B_NO_MEMORY; result = gIdMapper->InitStatus(); if (result != B_OK) { delete gIdMapper; gIdMapper = NULL; return result; } locker.Unlock(); AddressResolver* resolver; MountConfiguration config; char* path; result = ParseArguments(args, &resolver, &path, &config); if (result != B_OK) return result; MemoryDeleter pathDeleter(path); RPC::Server* server; result = gRPCServerManager->Acquire(&server, resolver, CreateNFS4Server); delete resolver; if (result != B_OK) return result; FileSystem* fs; result = FileSystem::Mount(&fs, server, path, volume->id, config); if (result != B_OK) { gRPCServerManager->Release(server); return result; } Inode* inode = fs->Root(); if (inode == NULL) { delete fs; gRPCServerManager->Release(server); return B_IO_ERROR; } volume->private_volume = fs; volume->ops = &gNFSv4VolumeOps; VnodeToInode* vti = new VnodeToInode(inode->ID(), fs); if (vti == NULL) { delete fs; gRPCServerManager->Release(server); return B_NO_MEMORY; } vti->Replace(inode); result = publish_vnode(volume, inode->ID(), vti, &gNFSv4VnodeOps, inode->Type(), 0); if (result != B_OK) return result; *_rootVnodeID = inode->ID(); TRACE("*_rootVnodeID = %" B_PRIi64, inode->ID()); return B_OK; }
status_t Volume::PublishNode(Node* node, uint32 flags) { return publish_vnode(fFSVolume, node->BlockIndex(), node, &gCheckSumFSVnodeOps, node->Mode(), flags); }
status_t fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args, ino_t *_rootID) { nspace *ns; vnode *newNode = NULL; char lockname[32]; void *handle; unsigned long mountFlags = 0; status_t result = B_NO_ERROR; ERRPRINT("fs_mount - ENTER\n"); ns = ntfs_malloc(sizeof(nspace)); if (!ns) { result = ENOMEM; goto exit; } *ns = (nspace) { .state = NF_FreeClustersOutdate | NF_FreeMFTOutdate, .show_sys_files = false, .ro = false, .flags = 0 }; strcpy(ns->devicePath,device); sprintf(lockname, "ntfs_lock %lx", ns->id); recursive_lock_init_etc(&(ns->vlock), lockname, MUTEX_FLAG_CLONE_NAME); handle = load_driver_settings("ntfs"); ns->show_sys_files = ! (strcasecmp(get_driver_parameter(handle, "hide_sys_files", "true", "true"), "true") == 0); ns->ro = strcasecmp(get_driver_parameter(handle, "read_only", "false", "false"), "false") != 0; ns->noatime = strcasecmp(get_driver_parameter(handle, "no_atime", "true", "true"), "true") == 0; unload_driver_settings(handle); if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0) { mountFlags |= MS_RDONLY; ns->flags |= B_FS_IS_READONLY; } // TODO: this does not take read-only volumes into account! ns->ntvol = utils_mount_volume(device, mountFlags, true); if (ns->ntvol != NULL) result = B_NO_ERROR; else result = errno; if (result == B_NO_ERROR) { *_rootID = FILE_root; ns->id = _vol->id; _vol->private_volume = (void *)ns; _vol->ops = &gNTFSVolumeOps; newNode = (vnode*)ntfs_calloc(sizeof(vnode)); if (newNode == NULL) result = ENOMEM; else { newNode->vnid = *_rootID; newNode->parent_vnid = -1; result = publish_vnode(_vol, *_rootID, (void*)newNode, &gNTFSVnodeOps, S_IFDIR, 0); if (result != B_NO_ERROR) { free(ns); result = EINVAL; goto exit; } else { result = B_NO_ERROR; ntfs_mark_free_space_outdated(ns); ntfs_calc_free_space(ns); } } } exit: ERRPRINT("fs_mount - EXIT, result code is %s\n", strerror(result)); return result; } status_t fs_unmount(fs_volume *_vol) { nspace *ns = (nspace*)_vol->private_volume; status_t result = B_NO_ERROR; ERRPRINT("fs_unmount - ENTER\n"); ntfs_umount(ns->ntvol, true); recursive_lock_destroy(&(ns->vlock)); free(ns); ERRPRINT("fs_unmount - EXIT, result is %s\n", strerror(result)); return result; }
status_t Volume::Mount(const char* deviceName, uint32 flags) { // TODO: validate the FS in write mode as well! #if (B_HOST_IS_LENDIAN && defined(BFS_BIG_ENDIAN_ONLY)) \ || (B_HOST_IS_BENDIAN && defined(BFS_LITTLE_ENDIAN_ONLY)) // in big endian mode, we only mount read-only for now flags |= B_MOUNT_READ_ONLY; #endif DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0 ? O_RDONLY : O_RDWR); fDevice = opener.Device(); if (fDevice < B_OK) RETURN_ERROR(fDevice); if (opener.IsReadOnly()) fFlags |= VOLUME_READ_ONLY; // read the superblock if (Identify(fDevice, &fSuperBlock) != B_OK) { FATAL(("invalid superblock!\n")); return B_BAD_VALUE; } // initialize short hands to the superblock (to save byte swapping) fBlockSize = fSuperBlock.BlockSize(); fBlockShift = fSuperBlock.BlockShift(); fAllocationGroupShift = fSuperBlock.AllocationGroupShift(); // check if the device size is large enough to hold the file system off_t diskSize; if (opener.GetSize(&diskSize, &fDeviceBlockSize) != B_OK) RETURN_ERROR(B_ERROR); if (diskSize < (NumBlocks() << BlockShift())) RETURN_ERROR(B_BAD_VALUE); // set the current log pointers, so that journaling will work correctly fLogStart = fSuperBlock.LogStart(); fLogEnd = fSuperBlock.LogEnd(); if ((fBlockCache = opener.InitCache(NumBlocks(), fBlockSize)) == NULL) return B_ERROR; fJournal = new(std::nothrow) Journal(this); if (fJournal == NULL) return B_NO_MEMORY; status_t status = fJournal->InitCheck(); if (status < B_OK) { FATAL(("could not initialize journal: %s!\n", strerror(status))); return status; } // replaying the log is the first thing we will do on this disk status = fJournal->ReplayLog(); if (status != B_OK) { FATAL(("Replaying log failed, data may be corrupted, volume " "read-only.\n")); fFlags |= VOLUME_READ_ONLY; // TODO: if this is the boot volume, Bootscript will assume this // is a CD... // TODO: it would be nice to have a user visible alert instead // of letting him just find this in the syslog. } status = fBlockAllocator.Initialize(); if (status != B_OK) { FATAL(("could not initialize block bitmap allocator!\n")); return status; } fRootNode = new(std::nothrow) Inode(this, ToVnode(Root())); if (fRootNode != NULL && fRootNode->InitCheck() == B_OK) { status = publish_vnode(fVolume, ToVnode(Root()), (void*)fRootNode, &gBFSVnodeOps, fRootNode->Mode(), 0); if (status == B_OK) { // try to get indices root dir if (!Indices().IsZero()) { fIndicesNode = new(std::nothrow) Inode(this, ToVnode(Indices())); } if (fIndicesNode == NULL || fIndicesNode->InitCheck() < B_OK || !fIndicesNode->IsContainer()) { INFORM(("bfs: volume doesn't have indices!\n")); if (fIndicesNode) { // if this is the case, the index root node is gone bad, // and BFS switch to read-only mode fFlags |= VOLUME_READ_ONLY; delete fIndicesNode; fIndicesNode = NULL; } } else { // we don't use the vnode layer to access the indices node } } else { FATAL(("could not create root node: publish_vnode() failed!\n")); delete fRootNode; return status; } } else { status = B_BAD_VALUE; FATAL(("could not create root node!\n")); return status; } // all went fine opener.Keep(); return B_OK; }
static status_t ext2_create_symlink(fs_volume* _volume, fs_vnode* _directory, const char* name, const char* path, int mode) { TRACE("ext2_create_symlink()\n"); Volume* volume = (Volume*)_volume->private_volume; Inode* directory = (Inode*)_directory->private_node; if (volume->IsReadOnly()) return B_READ_ONLY_DEVICE; if (!directory->IsDirectory()) return B_BAD_TYPE; status_t status = directory->CheckPermissions(W_OK); if (status != B_OK) return status; TRACE("ext2_create_symlink(): Starting transaction\n"); Transaction transaction(volume->GetJournal()); Inode* link; ino_t id; status = Inode::Create(transaction, directory, name, S_SYMLINK | 0777, 0, (uint8)EXT2_TYPE_SYMLINK, NULL, &id, &link); if (status != B_OK) return status; // TODO: We have to prepare the link before publishing? size_t length = strlen(path); TRACE("ext2_create_symlink(): Path (%s) length: %d\n", path, (int)length); if (length < EXT2_SHORT_SYMLINK_LENGTH) { strcpy(link->Node().symlink, path); link->Node().SetSize((uint32)length); TRACE("ext2_create_symlink(): Publishing vnode\n"); publish_vnode(volume->FSVolume(), id, link, &gExt2VnodeOps, link->Mode(), 0); put_vnode(volume->FSVolume(), id); } else { TRACE("ext2_create_symlink(): Publishing vnode\n"); publish_vnode(volume->FSVolume(), id, link, &gExt2VnodeOps, link->Mode(), 0); put_vnode(volume->FSVolume(), id); if (!link->HasFileCache()) { status = link->CreateFileCache(); if (status != B_OK) return status; } size_t written = length; status = link->WriteAt(transaction, 0, (const uint8*)path, &written); if (status == B_OK && written != length) status = B_IO_ERROR; } if (status == B_OK) status = link->WriteBack(transaction); entry_cache_add(volume->ID(), directory->ID(), name, id); status = transaction.Done(); if (status != B_OK) { entry_cache_remove(volume->ID(), directory->ID(), name); return status; } notify_entry_created(volume->ID(), directory->ID(), name, id); TRACE("ext2_create_symlink(): Done\n"); return status; }