bool MountDevice()

in host/common/sun/portablehelpersminor.cpp [1686:1914]


bool MountDevice(const std::string& device,const std::string& mountPoint,const std::string& fsType,bool bSetReadOnly, int &exitCode, 
                 std::string &errorMsg)
{
    if ( mountPoint.empty())
    {
        std::stringstream strerr;
        strerr << "Empty mountpoint specified.";
        strerr << "Cannot mount device " << device << '\n';
        DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
        errorMsg = strerr.str();
        return false;    
    }

    std::string errmsg;
    if(!IsValidMountPoint(mountPoint,errmsg))
    {
        std::stringstream strerr;
        strerr << "Cannot mount device " << device << " on mount point " << mountPoint << ". " << errmsg << "\n";
        DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
        errorMsg = strerr.str();
        return false;
    }

    if(SVMakeSureDirectoryPathExists(mountPoint.c_str()).failed())
    {
        std::stringstream strerr;
        strerr << "Failed to create mount point directory " << mountPoint
            << '\n';
        DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
        errorMsg = strerr.str();
        return false;
    }

    bool bCanMount = false;
    bool remount   = false;
    std::string flag;

    if(bSetReadOnly)
        flag="ro ";
    else
        flag="rw ";


    std::string sFileSystem = fsType;
    if(sFileSystem == "")
    {
        /* NEEDTOASK:
        * Linux handles this situation by specifying
        * auto as the filesystem. There is not equivalent
        * of auto in solaris. No manual page mentions about autofs
        * being similar to auto filesystem type in linux.
        * (linux manual page recommends against use of auto)
        * and even if we mount using autofs, it gets mounted
        * but ls on mountpoint hangs
        * sFileSystem = "autofs"; */

        std::stringstream strerr;
        strerr << "The filesystem supplied to mount is empty.";
        strerr << "Hence cannot mount device " << device << '\n';
        DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
        errorMsg = strerr.str();
        return false;    
    }

    std::string flags = flag;   //This is used only in case of Uncomment FSTAB. flag gets updated with -o remount where as flags doesn't.
    std::string sMount = "";
    std::string mode;
    if ( IsVolumeMounted(device,sMount,mode))
    {
        if ( sMount == mountPoint) //need to check if mode is same or not. If the mode is same, we will say already mounted, else we will do ewmount
        {
            if ("ufs" == sFileSystem)
            {
                bCanMount = true; 
                flag+="-o remount ";
            }
            else
            {
                std::stringstream strerr;
                strerr << "the device " << device 
                    << " is already mounted on " << sMount << '\n';
                DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
                errorMsg = strerr.str();
                return false;
            }
        }
        else
        {
            bCanMount = false;
            std::stringstream strerr;
            strerr << "Failed to unhide volume "
                << "since already visible on mount point " << sMount
                << " and requested mount point is " << mountPoint << '\n';
            DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
            errorMsg = strerr.str();
            return false;
        }
    }
    else /* volume is  not mounted */
    {    
        bCanMount = true;    
    }

    if ( bCanMount)
    {
        sFileSystem = ToLower(sFileSystem);
        if(!strcmp(sFileSystem.c_str(),"fat32") ||
            !strcmp(sFileSystem.c_str(),"fat")   ||
            !strcmp(sFileSystem.c_str(), "vfat"))
        {
            sFileSystem = "pcfs";
        }

        std::string fsmount;

        /* mount -F pcfs -o rw special mntpoint */
        fsmount += MOUNT_COMMAND;
        fsmount += " ";
        fsmount += OPTION_TO_SPECIFY_FILESYSTEM;
        fsmount += " ";
        fsmount += sFileSystem.c_str();
        fsmount += " -o ";
        fsmount += flag ;
        fsmount += " ";
        fsmount += device.c_str() ;
        fsmount += " ";
        fsmount += "\"";
        fsmount += mountPoint.c_str() ;
        fsmount += "\"";

        DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s THE MOUNT COMMAND FORMED is %s\n", LINE_NO, FILE_NAME, fsmount.c_str());

        std::string fsck_replay;
        std::string fsck_full;

        // For vxfs filesystems, we need to run fsck 
        // with log replay when trying to perform mount
        // on a non frozen source image (ie without issuing a tag)

        // log replay: fsck -F vxfs -y special 
        fsck_replay += FSCK_COMMAND;
        fsck_replay += " ";
        fsck_replay += FSCK_FS_OPTION ;
        fsck_replay += " ";
        fsck_replay += sFileSystem.c_str();
        fsck_replay += " -y ";
        fsck_replay += device.c_str() ;

        // full fsck: fsck -F vxfs -y  -o full,nolog special
        fsck_full += FSCK_COMMAND;
        fsck_full += " ";
        fsck_full += FSCK_FS_OPTION ;
        fsck_full += " ";
        fsck_full += sFileSystem.c_str();
        fsck_full += " -y ";
        fsck_full += FSCK_FULL_OPTION ;
        fsck_full += " ";
        fsck_full += device.c_str() ;


        if(flag!=flags)
            remount=true;

        int retriesformount = 0;
        bool mounted = false; 
        bool fsck_replay_done = false;
        bool fsck_full_done = false;

        // fsck needs to be done only for vxfs when performing
        // read write mount. in other cases, we will set
        // fsck done as true so it does not get executed
        if(bSetReadOnly || strcmp(sFileSystem.c_str(),"vxfs"))
        {
            fsck_replay_done = true;
            fsck_full_done = true;
        }

        do
        {
            DebugPrintf(SV_LOG_INFO, "executing %s...\n", fsmount.c_str());
            mounted = ExecuteInmCommand(fsmount, errorMsg, exitCode);
            if (mounted)
            {
                return true;
            } 
            else
            {
                DebugPrintf(SV_LOG_DEBUG, 
                    "mount %s with filesystem %s failed on %s with error message = %s. Retrying again\n",
                    device.c_str(),sFileSystem.c_str(),mountPoint.c_str(), errorMsg.c_str());
            }

            retriesformount++;
            if(!fsck_replay_done)
            {
                DebugPrintf(SV_LOG_INFO, "executing %s...\n", fsck_replay.c_str());
                if(!ExecuteInmCommand(fsck_replay, errorMsg, exitCode))
                {
                    DebugPrintf(SV_LOG_INFO,
                        "%s failed with exit code (%d) error message = %s.\n",
                        fsck_replay.c_str(), exitCode, errorMsg.c_str());
                }            
                fsck_replay_done = true;
                continue;
            }

            if(!fsck_full_done)
            {
                DebugPrintf(SV_LOG_INFO, "executing %s...\n", fsck_full.c_str());
                if(!ExecuteInmCommand(fsck_full, errorMsg, exitCode))
                {
                    DebugPrintf(SV_LOG_INFO,
                        "%s failed with exit code (%d) error message = %s.\n",
                        fsck_full.c_str(), exitCode, errorMsg.c_str());
                }
                fsck_full_done = true;
                continue;
            }

        } while (retriesformount < RETRIES_FOR_MOUNT);

        DebugPrintf(SV_LOG_ERROR, 
            "mount %s with filesystem %s failed on %s with error message = %s\n",
            device.c_str(),sFileSystem.c_str(),mountPoint.c_str(), errorMsg.c_str());

        return false;
    }
    return true;
}