U NIVERSIDADE DE L ISBOA Faculdade de Ciências Departamento de Informática SUBSTRATO DE ARMAZENAMENTO PARA SISTEMAS DE FICHEIROS SEGUROS PARA CLOUDS-OF-CLOUDS Tiago Moreno Oliveira DISSERTAÇÃO MESTRADO EM ENGENHARIA INFORMÁTICA Especialização em Arquitectura, Sistemas e Redes de Computadores 2012 U NIVERSIDADE DE L ISBOA Faculdade de Ciências Departamento de Informática SUBSTRATO DE ARMAZENAMENTO PARA SISTEMAS DE FICHEIROS SEGUROS PARA CLOUDS-OF-CLOUDS Tiago Moreno Oliveira DISSERTAÇÃO Dissertação orientada pelo Prof. Doutor Alysson Neves Bessani e co-orientada pelo Prof. Doutor Marcelo Pasin MESTRADO EM ENGENHARIA INFORMÁTICA Especialização em Arquitectura, Sistemas e Redes de Computadores 2012 Agradecimentos Em primeiro lugar quero agradecer a toda a minha famı́lia. Em especial aos meus pais por toda a educação, dedicação, valores e amor que me deram durante toda a minha vida. Sem o vosso apoio não tinha chegado onde cheguei. São os melhores pais do mundo. Aos meus maninhos mais novos, que eu sei que me adoram. Dava tudo por eles e sei que eles davam tudo por mim. Tenho muito orgulho em vocês. Ao meu tio Luı́s, um muito obrigado pelas palavras e apoio que sempre me deste. À minha avó Quim, por todas as orações que eu sei que ela rezou e reza por mim. Quero também agradecer a duas pessoas muito especiais que nunca deixaram e nunca deixarão de estar presentes na minha vida, à minha avó Ana e ao meu tio Dimas. Obrigado famı́lia. Em segundo lugar quero agradecer à minha namorada, Patrı́cia. A sua compreensão, motivação, amor e amizade foram muito importantes para mim. Em todos os momentos, bons ou menos bons, tu sempre me deste coragem. Obrigado por estares sempre presente e por seres quem és. Quero também deixar uma palavra de agradecimento a todos os meus amigos. Em especial a todos os meus companheiros de casa, com quem eu partilhei momentos de risada total, o Zabibu, o Fernandinho, o Veiga, e em especial o Tozé. Ao pessoal de Ficalho, que quando nos encontramos é para a desgraça, o Rato, o Manel, a Filipa, o Zé Gato, o Mikel, a Inês, o Varela, o Alacrau ,o Zé Francisco e a Mónica. Ao pessoal que me acompanhou na minha vida académica, o Ricardo, o Guns, o Marcos, o Jonny, o Reis, o Diogo, o Teixeira, o Gordo, o Panka, e o Chico. Com eles passei os momentos mais duros e mais alucinantes que a faculdade nos proporcionou. Um obrigado especial ao Ricardo, que foi a pessoa com quem mais horas passei nestes últimos 5 anos, por toda a ajuda e companheirismo. Sei que posso contar com todos vocês para qualquer coisa. Obrigado por toda a força e amizade. Deixo também um obrigado muito especial para o meu orientador, Professor Alysson Bessani, e co-orientador, Professor Marcelo Pasin, pela orientação e ajuda que me deram neste projecto. O “à vontade” com que me deixaram, a forma aberta como trocámos ideias, e todo o bom ambiente que me foi concedido foram fundamentais para o meu empenho, motivação e boa disposição. Com vocês aprendi muito. Muito obrigado. Um sincero obrigado a todos aqueles que influenciaram, de uma forma ou de outra, o meu crescimento como pessoa e como profissional. iii Às boas memórias. Resumo O armazenamento de dados em provedores de clouds tem vindo a tornar-se bastante comum entre empresas, programadores e utilizadores. Porém existem ainda algumas dificuldades de acessos aos mesmos. Estas dificuldades têm vindo a ser mitigadas pelo uso de sistemas de ficheiros que armazenam os dados, de uma forma transparente, nas clouds. Contudo, nestes sistemas, a disponibilidade dos dados é comprometida, pois estes dependem da disponibilidade do provedor de armazenamento em uso. O DepSky é um serviço de armazenamento tolerante a faltas bizantinas que melhorar a disponibilidade dos dados armazenados nas clouds através da replicação dos dados por um conjunto destas, ao mesmo tempo que garante a integridade e confidencialidade dos mesmos. Ao conceito de armazenar os dados em várias clouds foi dado o nome cloud-of-clouds. Assim nasce o C2FS, um sistema de ficheiros seguro e fiável para cloud-of-clouds, que vem cobrir estas limitações pois, ao mesmo tempo que fornece uma interface do estilo POSIX, armazena os dados em múltiplas clouds através do DepSky. Este projecto apresenta o serviço de armazenamento construı́do para o C2FS que visa melhorar a utilização do Depsky através do uso intensivo de dois nı́veis de cache, o de memória e o de disco. Este serviço suporta também dois modelos de envio de dados para as clouds, podendo este ser sı́ncrono ou assı́ncrono. O nı́vel de consistência fornecido pelo C2FS é influenciado pelo cliente aquando da configuração do nı́vel de cache e do modelo de envio de dados. Neste projecto é também apresentada uma avaliação experimental que mostra o desempenho do serviço de armazenamento de dados com diferentes configurações. Os resultados obtidos mostram que, ao mesmo tempo que as diversas limitações mencionadas são ultrapassadas, é fornecido um desempenho muito satisfatório. Palavras-chave: sistemas de ficheiros, armazenamento em clouds, computação em clouds, tolerância a faltas, cache vii Abstract Storing data in the cloud is becoming quite common today. However, there are still some difficulties related with how to access and manage this data. These difficulties are been mitigated by the use of cloud-backed file systems that store data, in a transparent manner, in the cloud. Nevertheless, with these systems, data availability is directly tied with the availability of the storage provider being used. Recently, the problem of cloud unavailability was addressed through the use multiple cloud providers (cloud-of-clouds). DepSky is a Byzantine fault-tolerant storage service, which has improved the availability of data stored in clouds through replication of data by a set of clouds, while ensuring the integrity and confidentiality. The project described in this thesis contributes to C2FS, a secure and dependable cloud-backed file system that addresses the mentioned limitations by providing a familiar file system interface and, at the same time, storing the data in cloud-of-clouds using DepSky. More specifically, it presents the C2FS storage service that aims improve the use os DepSky through intensive use of two cache levels: memory and disk. This service also supports two cloud data transfer models, which can be synchronous or asynchronous. The level of consistency provided by this service is controlled by the level of cache and data sending model parameters, as configured by the user. This thesis also presents an experimental evaluation that shows the performance of the storage service with different settings. The results show that, while the various mentioned limitations are overcomed, the system provides a very satisfactory performance. Keywords: file systems, cloud storage, clouds computing, Byzantine fault tolerance, cache ix Conteúdo Lista de Figuras xiii Lista de Tabelas xv 1 2 Introdução 1.1 Motivação . . . . . . . 1.2 Objectivos . . . . . . . 1.3 Contribuições . . . . . 1.4 Publicações . . . . . . 1.5 Planeamento . . . . . . 1.6 Estrutura do documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Trabalho relacionado 2.1 Serviços de Armazenamento . . . 2.1.1 Petal . . . . . . . . . . . 2.1.2 OceanStore . . . . . . . . 2.1.3 Ursa Minor . . . . . . . . 2.1.4 DepSky . . . . . . . . . . 2.1.5 Considerações Finais . . . 2.2 Sistemas de Ficheiros Distribuı́dos 2.2.1 Andrew File System . . . 2.2.2 Ceph . . . . . . . . . . . 2.2.3 CODA . . . . . . . . . . 2.2.4 Frangipani . . . . . . . . 2.2.5 Considerações Finais . . . 2.3 Sistemas de Ficheiros para Clouds 2.3.1 S3FS . . . . . . . . . . . 2.3.2 S3QL . . . . . . . . . . . 2.3.3 BlueSky . . . . . . . . . . 2.3.4 Frugal cloud File System . 2.3.5 Cumulus . . . . . . . . . xi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 3 3 4 4 5 . . . . . . . . . . . . . . . . . . 7 7 7 8 9 10 12 12 12 14 15 17 18 18 19 20 20 21 22 2.4 3 4 5 6 2.3.6 Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . Armazenamento de Dados do C2FS 3.1 C2FS . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Arquitectura . . . . . . . . . . . . . . . . 3.1.2 Modelo do Sistema . . . . . . . . . . . . . 3.2 FUSE . . . . . . . . . . . . . . . . . . . . . . . . 3.3 DepSky . . . . . . . . . . . . . . . . . . . . . . . 3.4 Serviço de Armazenamento . . . . . . . . . . . . . 3.4.1 Visão Geral da Gestão do Armazenamento 3.4.2 Algoritmos de Gestão de Armazenamento . 3.4.3 Modelo de Envio de Dados . . . . . . . . . 3.4.4 Durabilidade dos Dados . . . . . . . . . . 3.4.5 Colector de Lixo . . . . . . . . . . . . . . 3.5 Considerações Finais . . . . . . . . . . . . . . . . 23 23 . . . . . . . . . . . . 25 25 25 26 27 28 31 32 34 43 44 45 47 . . . . 49 49 50 55 57 . . . . . 59 59 60 61 63 65 Conclusão 6.1 Trabalho Futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 67 Concretização do Serviço de Armazenamento 4.1 Diagrama de Classes . . . . . . . . . . . 4.2 Diagramas de Sequência . . . . . . . . . 4.3 Agente C2FS . . . . . . . . . . . . . . . 4.4 Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Avaliação 5.1 Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Latência das Escritas e Leituras de Dados . . . . . . . . . . . . . . 5.3 Desempenho do Serviço de Armazenamento do C2FS . . . . . . . . 5.4 Comparação do C2FS com outros Sistemas de Ficheiros para Cloud 5.5 Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . . Bibliografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 xii Lista de Figuras 2.1 2.2 2.3 2.4 2.5 2.6 2.7 Arquitectura do Petal [29]. . . . . . . . . . . . . . Arquitectura do Ursa Minor [18]. . . . . . . . . . . Arquitectura do DepSky [19]. . . . . . . . . . . . . Arquitectura do Andrew File System. . . . . . . . Arquitectura do Ceph [47]. . . . . . . . . . . . . . Arquitectura do Frangipani [43]. . . . . . . . . . . Arquitectura de Sistemas de Ficheiros para clouds. . . . . . . . 8 10 11 13 14 17 19 3.1 3.2 3.3 3.4 Arquitectura do C2FS. . . . . . . . . . . . . . . . . . . . . . . . . . . . Caminho percorrido por cada chamada ao sistema. . . . . . . . . . . . . Fluxo dos dados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Desencadeamento das chamadas ao sistema no serviço de armazenamento. 26 28 33 43 4.1 4.2 4.3 4.4 Modelo de classes do sistema. . . Operação de leitura das clouds. . . Operação de escrita em cache. . . Operação de escrita para as clouds. . . . . 51 54 55 56 5.1 5.2 Latência das escritas e leituras (em segundos) para a cloud-of-clouds . . . Tempo de execução (em segundos) do IOzone e PostMark para escritas sı́ncronas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tempo de execução (em segundos) do IOzone e PostMark para escritas assı́ncronas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Latência e throughput das operações de escrita e leitura não sequenciais. Valores medidos através da execução do workload randomrw do Filebench 61 5.3 5.4 . . . . xiii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 62 63 Lista de Tabelas 3.1 3.2 Operações FUSE-J. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Durabilidade dos dados. . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 44 4.1 Linhas de código das classes do serviço de armazenamento . . . . . . . . 52 5.1 5.2 Comparação dos tempos de execução (em segundos) com o S3FS. . . . . Comparação dos tempos de execução (em segundos) com o S3QL. . . . . 64 65 xv Capı́tulo 1 Introdução Nos dias de hoje, os utilizadores normais de computadores e internet, os programadores ou até mesmo empresas têm vindo a fazer cada vez mais uso dos diversos provedores de armazenamento baseados nas clouds (cloud storage), para armazenar os seus dados. A crescente popularização destes serviços deve-se à necessidade e/ou vontade que os utilizadores têm em exteriorizar os seus dados tanto para fins de backup e facilidade de acesso aos mesmos, como para a partilha de ficheiros. Alguns exemplos destes serviços são o iCloud [5], a Amazon S3 [4] e o Google Storage [9]. Com este aumento de utilização das clouds para armazenar dados, nasce a necessidade de estudar as abstracções necessárias para que os programadores possam fazer as suas aplicações acederem às clouds. O modelo mais utilizado hoje em dia para tal finalidade é a disponibilização de web services por parte das clouds que podem ser acedidos via REST, SOAP ou XML-RPC. Este modelo não é nada mais que uma instância do modelo clássico de chamada remota a procedimentos (RPC) que, apesar de ser muito bom para a troca directa de mensagens, é muito mais orientado para controlo que para os dados. Um modelo de acesso bem mais atraente aos olhos dos utilizadores é a gestão de ficheiros na cloud através de um sistema de ficheiros. Esta abstracção fornece aos utilizadores uma forma muito mais simples e familiar para a gestão de dados nos provedores de armazenamento. Esta ideia já tem sido suportada por alguns sistemas de ficheiros que armazenam os dados em clouds como o S3FS [16] e o BlueSky[45]. Porém, todos estes sistemas mostram algumas limitações devido ao facto de armazenarem os dados num só provedor de armazenamento, dependendo assim da disponibilidade, da polı́tica de acesso e dos custos oferecidos por este. A equipa de investigação Navigators têm estado a trabalhar num projecto financiado pela Comissão Europeia chamado TClouds [14] que tem como principal objectivo eliminar essas limitações. Este objectivo é alcançado através do uso de vários provedores em nuvem ao invés de um só. Este colectivo de clouds é denominado de cloud-of-clouds. Neste contexto, nasce a ideia de concretizar um sistema de ficheiros que, ao mesmo tempo que fornece uma semântica bem conhecida aos utilizadores, semântica essa sim1 Capı́tulo 1. Introdução 2 ilar à definida pelo padrão POSIX (concretizado pelos sistemas Unix) [13], elimina as limitações que os sistemas existentes apresentam. Um dos principais objectivos é tornar a gestão de dados na cloud-of-clouds tão simples quanto a gestão de dados num sistema de ficheiros local. A este sistema de ficheiros foi dado o nome de C2FS (Cloud-of-Clouds File System). Com esta finalidade, surge este Projecto de Engenharia Informática (PEI) que se foca assim no desenho do substracto de armazenamento para este sistema de ficheiros e tem como objectivos fundamentais a construção da abstracção de discos virtuais onde os blocos de dados serão armazenados e a sua integração numa interface de sistema de ficheiros do estilo POSIX. 1.1 Motivação Como já mencionado, existem alguns sistemas de ficheiros exploraram a ideia de armazenar os seus dados em serviços de armazenamento como as clouds. O uso destes serviços para armazenar dados apresenta algumas vantagens como a facilidade de acesso que os utilizadores têm para aceder aos dados, o seu baixo custo e o seu modelo de pagamento conforme o uso, que não necessita investimento inicial. Contudo, o uso de uma só cloud por estes sistemas de ficheiros para o armazenamento dos dados acarreta algumas desvantagens que podem ser bastante problemáticas em condições adversas. A primeira desvantagem prende-se no facto da disponibilidade dos dados ser directamente afectada pela disponibilidade do provedor utilizado, isto é, se o provedor sofrer qualquer tipo de problema ou se a ligação até ele mostrar alguma deficiência os dados tornam-se inacessı́veis. Outra desvantagem prende-se com o acesso não controlado do provedor aos dados por ele armazenados, o que levanta algumas preocupações quando se quer armazenar informação crı́tica. Outro possı́vel perigo está relacionado com o facto de o provedor poder corromper os dados devido a faltas (maliciosas ou não) na sua infraestrutura. A última limitação a apontar diz respeito ao possı́vel aumento do preço por parte do provedor de armazenamento, que pode impedir os utilizadores de remover de lá os seus dados. Este acontecimento é conhecido por vendor lock-in [23]. Recentemente, foi provado pelo serviço de armazenamento DepSky [19] que estas limitações podem ser ultrapassadas se aliarmos o uso de provedores independentes a técnicas de tolerância a faltas e a criptografia. Este sistema armazena os blocos de dados numa cloud-of-clouds para que estes se mantenham confidenciais e disponı́veis mesmo que uma fracção dos provedores sejam faltosos, tolerando assim faltas bizantinas (isto é, quando apresentam um comportamento arbitrário fora da sua especificação). Contudo, a interface disponibilizada pelo DepSky é de baixo nı́vel pois assemelha-se a um disco virtual onde os blocos de dados são armazenados. O uso deste tipo de interface é bastante complicado para programadores que têm intenção de construir aplicações que armazenam Capı́tulo 1. Introdução 3 os dados nas clouds, e ainda mais complicado para utilizadores que apenas desejam armazenar os seus ficheiros na cloud-of-clouds e que não têm nenhum conhecimento e experiência sobre como usar este tipo de interface. Como referido na secção anterior, uma abstracção muito mais familiar aos utilizadores e/ou programadores são os sistemas de ficheiros. Constitui assim um desafio interessante implementar um sistema de ficheiros que armazene os seus dados numa cloud-of-clouds através do DepSky. A concretização deste sistema de ficheiros consegue assim unir todas as garantias fornecidas pelo DepSky a uma interface bem conhecida. 1.2 Objectivos Para a construção do C2FS é necessário a integração de uma série de serviços distintos: o DepSpace, o DepSky e o FUSE. O DepSpace [20] é um sistema de coordenação tolerantes a faltas bizantinas. A utilização deste serviço no C2FS tem como principais objectivos fornecer o serviço de directorias para a gestão dos metadados e o serviço de locks para coordenar escritas concorrentes sobre o mesmo ficheiro. O desenvolvimento destes dois serviços e a sua integração no C2FS foi efectuado em outro Projecto de Engenharia Informática [32]. Este PEI foca-se no uso do FUSE [7] e do DepSky para contrução de um serviço de armazenamento para o C2FS. Assim, os objectivos especı́ficos deste PEI são: • Estudar os serviços de armazenamento e sistemas de ficheiros existentes, principalmente os que armazenam dados nas clouds. • Estudar e implementar uma interface de sistemas de ficheiros. • Estudar e modificar a implementação do DepSky de modo a este responder o melhor possı́vel às necessidades do C2FS. • Concretizar um serviço de armazenamento cliente do DepSky e integrá-lo na interface de sistemas de ficheiros disponibilizada pelo FUSE. • Avaliar este serviço para mostrar que ao mesmo tempo que fornece mais garantias, tem um desempenho similar aos dos sistemas existentes que armazenam dados nas clouds. 1.3 Contribuições Este projecto contribuiu com alguns pontos essenciais para o desenho do C2FS. Uma das contribuições foi a disponibilização da interface de sistemas de ficheiros para o C2FS através do módulo FUSE. Este é um serviço que nos permite implementar sistemas de Capı́tulo 1. Introdução 4 ficheiros a nı́vel do utilizador, não sendo assim necessário quaisquer alterações a nı́vel do kernel. Outra contribuição foi a introdução de novas técnicas do DepSky. Outra contribuição importante foi a concretização do serviço de armazenamento de dados que usa os discos virtuais do DepSky para armazenar os dados na cloud-of-clouds. Este serviço fornece dois nı́veis diferentes de cache (cache em disco e cache em memória) e duas formas distintas de enviar os dados para as clouds sendo elas sı́ncrona e assı́ncrona. Os utilizadores podem escolher qual o nı́vel de cache pretendido e qual a forma de envio a utilizar de modo a preencher as suas necessidades. Por fim, foi concretizado um colector de lixo para eliminar todos os dados dispensáveis ainda armazenados na cloud-of-clouds. 1.4 Publicações O trabalho descrito nesta dissertação foi contribuiu para a publicação de um artigo cientı́fico no INForum 2012, na track “Computação Paralela, Distribuı́da e de Larga Escala” [33]. 1.5 Planeamento No inı́cio o plano de trabalho para este PEI consistia em: • Tarefa 1 (Setembro e Outubro 2011): Revisão bibliográfica e estudo das tecnologias envolvidas (acesso aos provedores de armazenamento em cloud e construção de sistemas de ficheiro em espaço de utilizador). • Tarefa 2 (Novembro 2011): Desenho da abstracção de disco virtual e sua integração no sistema de ficheiros como um todo (tarefa a ser realizada em conjunto com outros membros do Navigators que estejam a trabalhar no sistema de ficheiro). • Tarefa 3 (Dezembro 2011): Evolução do DepSky visando robustez e facilidade de utilização. • Tarefa 4 (Janeiro e Fevereiro 2012): Concretização de um cliente FUSE para o disco virtual baseado no DepSky. • Tarefa 5 (Março 2012): Integração do trabalho realizado com os outros mecanismos do sistema de ficheiro (nomeadamente a coordenação e serviço de nomes e directorias). • Tarefa 6 (Abril 2012): Avaliação do sistema através de benchmarks de sistemas de ficheiros utilizados na indústria. • Tarefa 7 (Maio 2012): Escrita da tese e, idealmente, de um artigo cientifico para workshop ou conferência de médio porte. Capı́tulo 1. Introdução 5 A ordem de trabalho que foi desenvolvida neste projecto seguiu este planeamento até a tarefa 4. A tarefa 5, 6 e 7 sofreram alguns atrasos devido a optimizações que foram efectuadas no serviço de armazenamento. 1.6 Estrutura do documento Esta dissertação está organizada da seguinte forma: • Capı́tulo 2 - Este capı́tulo apresenta o estudo realizado sobre o trabalho relacionado com o sistema de ficheiros que se pretendia desenvolver. Aqui são descritas as caracterı́sticas dos serviços de armazenamento, de alguns sistemas de ficheiros distribuı́dos, e dos sistemas de ficheiros para clouds existentes. • Capı́tulo 3 - Neste capı́tulo é primeiramente apresentada a arquitectura do C2FS. Posteriormente é apresentada a interface de sistemas de ficheiros implementada e são explicadas as modificações mais relevantes efectuadas a nı́vel do Depsky. Por último é descrito em pormenor o serviço de armazenamento concretizado. • Capı́tulo 4 - Aqui são apresentados alguns detalhes de concretização do serviço de armazenamento. • Capı́tulo 5 - Este capı́tulo apresenta uma avaliação preliminar do C2FS, efectuada essencialmente sobre as operações de escrita e leitura de dados, focando-nos assim mais no desempenho do serviço de armazenamento concretizado. É também efectuada uma comparação entre o C2FS e outros dois sistemas de ficheiros para clouds, sendo eles o S3FS [16] e o S3QL [17]. • Capı́tulo 6 - Este último capı́tulo descreve as conclusões a retirar do trabalho desenvolvido e são introduzidas abordagens a seguir no futuro de forma a aumentar o desempenho do C2FS. Capı́tulo 1. Introdução 6 Capı́tulo 2 Trabalho relacionado Nesta capı́tulo são primeiro apresentados, na secção 2.1, alguns dos serviço de armazenamento representativos. Posteriormente, na secção 2.2, são apresentados alguns sistemas ficheiros distribuı́dos tradicionais que foram concretizados sobre o modelo clienteservidor. Por fim, na secção 2.3, são descritos os sistemas de ficheiros que utilizam clouds para armazenar os dados. 2.1 Serviços de Armazenamento Nesta secção são introduzidos alguns serviços de armazenamento estudados. Estes serviços diferem da abstracção de sistemas de ficheiros por duas principais razões: primeiro não permitem a criação de directorias e da estrutura em árvore que os sistemas de ficheiros usualmente têm; em segundo não implementam uma interface de sistemas de ficheiros, fornecendo só uma pequena lista de operações para a leitura e escrita de dados. Contudo, alguns dos sistemas de ficheiros existentes utilizam estes tipos de serviços para armazenar os seus dados. 2.1.1 Petal Petal [29] é um sistema de armazenamento distribuı́do fácil de gerir, que fornece aos seus clientes (sistemas de ficheiros e bases de dados) uma total abstracção da sua visualização fı́sica, mostrando-lhes uma colecção de discos virtuais que podem ser acedidos através de uma interface de chamada remota de procedimentos (RPC). Cada disco virtual fornece um espaço de 264 bytes para armazenamento, onde cada leitura ou escrita é feita em blocos de tamanho variável. A sua arquitectura fı́sica baseia-se num conjunto de servidores de armazenamento distribuı́dos que cooperam entre si como mostra a figura 2.1. O sistema replica cada bloco de dados por cada par de servidores vizinhos, isto significa, que são mantidas para cada bloco de dados duas réplicas. Assim mesmo que um servidor falhe, os pedidos que a este são efectuados podem ser respondidos pelo servidor 7 Capı́tulo 2. Trabalho relacionado 8 Figura 2.1: Arquitectura do Petal [29]. vizinho que mantenha a outra réplica. Devido a este mecanismo de replicação, o Petal faz também balanceamento de carga pelos diferentes servidores. Algoritmos distribuı́dos asseguram que todos os servidores têm a mesma carga e obtêm informação acerca de qualquer falha existente no sistema. Um dos serviços prestado pelo Petal é a possibilidade de efectuar snapshots. Estas snapshots são imagens consistentes dos discos fı́sicos que permitem aos clientes fazerem backup do sistema. Para a criação destas snapshots é necessário uma pausa do sistema por um perı́odo de tempo, o que pode prejudicar a disponibilidade do mesmo. Outra importante funcionalidade é o facto de os servidores poderem recuperar depois de uma eventual falha devido a manutenção de um log com os seus blocos de dados. O sistema permite a adição e remoção de discos fı́sicos com uma simples operação de reconfiguração. 2.1.2 OceanStore O OceanStore [28] é uma arquitectura para um sistema de armazenamento persistente à escala global. Ele consiste num conjunto de servidores altamente conectados espalhados pelo mundo, a que os clientes se podem conectar (podem estar conectados a mais que um servidor e estão ligados aos servidores geograficamente mais perto). Este sistema permite uma adaptação transparente e automática aquando da adição ou remoção de servidores. Os seus principais objectivos é permitir dados nómadas (dados que podem ser guardados em qualquer lugar a qualquer instante) e construir um sistema que corra sobre servidores não confiáveis suportando faltas bizantinas. Como os dados podem fluir pela internet de um servidor para outro, são necessários algoritmos que encontrem onde os dados estão guardados a um qualquer instante. Para tal são usados dois algoritmos distintos. Primeiro é executado uma algoritmo probabilı́stico baseando-se no facto de os dados poderem estar no servidor vizinho (i.e., mais próximo) da localização do cliente. Este Capı́tulo 2. Trabalho relacionado 9 algoritmo é bastante rápido, mas só se os dados estiverem na vizinhança do cliente. Caso este falhe, é executado um algoritmo global que é mais lento, mas mais confiável. Este localiza os dados que não podem ser encontrados localmente através de uma estrutura de dados hierárquica de larga escala ao estilo ds difinida por Plaxton et al [35]. Cada objecto do sistema é identificado por um identificador único que é um resumo criptográfico (criado com a técnica SHA-1) gerado sobre a chave privada do cliente juntamente com informação introduzida por este. Para fornecer disponibilidade, os objectos são replicados e guardados em múltiplos servidores geograficamente distribuı́dos. Existem duas camadas de réplicas para fazer actualizações (mudança nos dados guardados) sem ocorrer conflitos: a primária e a secundária. A camada primária decide se uma actualização pode ser efectuada ou deve ser abortada através do protocolo de acordo bizantino [21]. Quando a camada primária toma uma decisão, faz multicast do resultado para as réplicas da camada secundária para estas procederem à actualização. Os objectos são representados em duas formas: activa e arquivada. Todas as actualizações são efectuadas sobre objectos na forma activa enquanto que objectos arquivados representam uma versão permanente só de leitura. Os objectos são armazenados utilizando códigos de apagamento. Para assegurar a integridade de cada fragmento produzido pelos códigos de apagamento aquando da sua recuperação é utilizado um método de resumo criptográfico hierárquico para verificá-los. 2.1.3 Ursa Minor Ursa Minor [18] é um sistema de armazenamento versátil baseado em clusters que fornece aos seus clientes a oportunidade de escolher o modo de armazenamento (códigos de apagamento ou replicação), o tamanho dos blocos, a localização dos dados, o modelo de falha dos servidores de armazenamento (paragem ou bizantino), número de falhas a tolerar e o modelo de tempo (assı́ncrono ou sı́ncrono). Este sistema permite também a reconfiguração de alguns destes parâmetros (e.g., modelo de tempo e tamanho dos blocos) para dados on-line. Parâmetros como o modelo de tempo e modelo de falha para os clientes e servidores compromete a performance, a disponibilidade e fiabilidade dos dados. Este sistema assume armazenamento baseado em objectos. O armazenamento destes objectos é feito seguindo o padrão de OSDs (object store devices) [24]. Cada objecto no Ursa Minor, além de ter os dados associados, guarda também informação acerca do tamanho dos blocos, ACLs e outros parâmetros. A figura 2.2 mostra a arquitectura do sistema. Os clientes para acederem aos objectos armazenado nos servidores de armazenamento acedem primeiro ao Object manager para obterem os metadados, isto é, a localização do objecto e a autorização para acede-lo. Como mencionado, existem duas formas de armazenar os dados nos nós de armazenamento: com replicação ou usando códigos de apagamento. O uso de códigos de apagamento melhora a performance do sistema. Para tal é utilizado um esquema de códigos Capı́tulo 2. Trabalho relacionado 10 Figura 2.2: Arquitectura do Ursa Minor [18]. de apagamento [34] em que primeiro, o bloco de dados é dividido em m fragmentos (stripe-fragments), e em segundo, estes fragmentos são utilizados para criar c (c é igual n menos m, em que n é número de servidores para replicar os objecto) fragmentos codificados (code-fragments) que fornecem a redundância necessária. Quaisquer m fragmentos podem reconstruir o bloco de dados original. Note-se que se m for igual a 1 é usado replicação. Para assegurar a integridade dos dados armazenados nos nós de armazenamento é computado um resumo criptográfico para cada fragmento seguindo o conceito de checksums cruzados [38] onde cada checksum cruzado é concatenado a cada fragmento. Aquando de uma operação de escrita, antes do envio dos dados para cada nó de armazenamento, cada fragmento é marcado com um timestamp único. Assim, na operação de leitura, os clientes têm que obter os blocos de dados dos servidores de armazenamento com o mesmo timestamp para obter os fragmentos do mesmo bloco de dados. É mantido um colector de lixo pois cada escrita cria uma versão nova dos fragmentos. Os nós de armazenamento usam uma cache write-back para evitar acessos ao disco aumentando assim a performance. Esta cache só mantêm fragmentos com o último timestamp. 2.1.4 DepSky O DepSky [19] é um serviço de armazenamento fiável e seguro que armazena os dados em múltiplas cloud formando assim uma cloud-of-clouds. Este conceito é introduzido na imagem 2.3 onde são utilizadas quatro diferentes clouds. Este serviço fornece alta disponibilidade, integridade e confidencialidade dos dados armazenados replicandoos, codificando-os e encriptando-os. Existem dois protocolos disponı́veis para usar este sistema: DepSky-A e DepSky-CA. DepSky-A fornece disponibilidade e integridade dos dados enquanto que o DepSky-CA assegura estas duas garantias acrescentado a confiden- Capı́tulo 2. Trabalho relacionado 11 cialidade dos mesmos. Figura 2.3: Arquitectura do DepSky [19]. Para suportar falhas bizantinas o DepSky utiliza um protocolo de quóruns (são necessários 3f + 1 servidores para suportar f falhas), efectuando cada operação (escrita ou leitura) em n − f clouds, onde n é o número total de clouds utilizadas. O DepSky implementa um registo onde são permitidos a cada instante um escritor e múltiplos leitores, pois os nós de armazenamento são incapazes de executar código que elimine conflitos entre escritas concorrentes. Os programadores acedem aos seus dados através de uma interface de armazenamento de objectos. Cada operação (e.g., leitura e escrita) é efectuada usando um objecto denominado data unit. Basicamente, cada data unit corresponde a um contentor em cada cloud. Cada contentor armazena todas as versões dos dados, pois cada operação de escrita cria uma nova versão. É também mantido em cada contentor um ficheiro de metadados que contém o número da versão mais actual armazenada e um resumo criptográfico para assegurar a integridade desta versão. Numa operação de escrita são primeiro escritos os dados e só depois os metadados. Esta sequência assegura que só irão ser lidos metadados de dados previamente armazenados no sistema. As versões antigas dos dados podem ser eliminados utilizando um protocolo para colectar lixo. Este modelo de dados abstrai para os cliente a heterogeneidade de armazenar dados em diferentes clouds. Como foi mencionado acima, o DepSky fornece dois protocolos para a manutenção dos dados na cloud-of-clouds. O DepSky-A garante disponibilidade replicando os dados na cloud-of-clouds usando técnicas de quóruns, e integridade computando um resumo criptográfico como descrito em cima. Apesar de assegurar estas duas garantias, o DepSky-A mostra-se inútil quando os programados precisam armazenar dados crı́ticos Capı́tulo 2. Trabalho relacionado 12 e confidenciais, pois os dados são replicados na forma de texto em claro. O protocolo DepSky-CA cobre esta limitação encriptando os dados com uma chave simétrica. Neste protocolo, são criados key shares através de um esquema de partilha de segredos e são utilizados códigos de apagamento para codificar os dados encriptados. Assim, é armazenado em cada cloud um fragmento codificado concatenado um key share (como são usadas 4 clouds, são gerados 4 key shares e 4 fragmentos codificados). 2.1.5 Considerações Finais Dos serviços de armazenamento descritos nestas secções, podemos verificar que só o Petal oferece uma interface para o armazenamento de blocos, enquanto que os restantes oferecem uma interface para o armazenamento de objecto. Ao invés do armazenamento baseado em blocos, o armazenamento baseado em objectos facilita o agrupamento de diferentes informações para cada bloco de dados armazenado, como também permite armazenar objectos de tamanho variável. Outra vantagem inerente ao uso de serviços de armazenamento de objectos refere-se ao facto de não ser necessário manter estruturas que nos indiquem onde cada bloco está armazenado, bastando utilizar o identificador do objecto para efectuar operações de escrita ou leitura. 2.2 Sistemas de Ficheiros Distribuı́dos Nesta secção são descritos alguns dos sistemas de ficheiros distribuı́dos que mais influenciaram alguns dos sistemas de ficheiros de hoje em dia. Um sistema de ficheiros distribuı́do é um sistema que permite aos programadores ou utilizadores armazenar os seus dados remotamente, ou seja, numa outra localização através da internet, exactamente da mesma forma que o fazem nos sistemas de ficheiros locais, sendo assim a transparência uma das principais propriedades destes [22]. Estes foram desenhados seguindo o conhecido modelo cliente-servidor de sistemas distribuı́dos. 2.2.1 Andrew File System O Andrew File System (AFS) [40] é um sistema de ficheiros antigo que foi desenvolvido para um ambiente de mais ou menos 5000 clientes. A sua arquitectura e design influenciaram muitos dos sistemas de ficheiros dos dias de hoje. Apesar de a cache ser o ponto chave do seu design, é dada uma grande atenção à segurança, à transparência da localização dos dados, à escalabilidade, à mobilidade do utilizador, à heterogeneidade e à partilha de dados. Existem duas principais entidades na sua arquitectura como mostra a figura 2.4: Vice e Virtue. A entidade Vice é o conjunto de servidores responsáveis de armazenar os dados que as várias estações de trabalho Virtue querem guardar. É importante referir que é assumido que o Vice é seguro. Cada estação Virtue foi concretizada em duas Capı́tulo 2. Trabalho relacionado 13 distintas partes: algumas modificações necessárias a nı́vel do kernel para ser possı́vel interceptar as chamadas ao sistema referentes a ficheiros pertencentes ao AFS, e a entidade que realmente comunica com o Vice e que gere a cache local denominada Venus. Figura 2.4: Arquitectura do Andrew File System. Para obter uma boa performance, mobilidade e escalabilidade, o AFS utiliza uma cache no lado do cliente e transfere os ficheiros completos para os servidores. A cache, além de manter os dados actualizados, guarda também informação sobre o seu estado e sobre a sua custódia. Este sistema de ficheiros só executa operações (escrita e leitura) em ficheiros que estejam em cache. Se um ficheiro não estiver em cache, então Venus comunica com o servidor Vice que mantem o ficheiro armazenado (os dados são só guardados num servidor) e transfere-o para a sua cache local. Para garantir que os ficheiros em cache têm uma vista coerente em diferentes estações de trabalho, o AFS usa um sistema de validação da cache que necessita alguma computação nos servidores pertencentes ao Vice. Basicamente, a Virtue notifica o Vice quando um ficheiro em cache é fechado e o Vice notifica as outras estações de trabalho que partilham o mesmo ficheiro de que o ficheiro foi modificado. Note-se que são armazenados ficheiros inteiros ao invés de blocos e que os ficheiros só são armazenados depois do seu fecho. Esta abordagem simplifica a recuperação de falhas das estações de trabalho. Para melhorar a disponibilidade dos dados guardados, o Vice replica versões só de leitura de ficheiros que são raramente modificados e frequentemente acedidos para leitura. Como é suposto que toda a rede é não confiável, todas as comunicações entre a Virtue e o Vice iniciam com um protocolo de autenticação que gera uma chave única para encriptar toda a informação trocada em cada conexão. Esta chave é obtida através de uma informação especı́fica do utilizador (password). É também na autenticação que é Capı́tulo 2. Trabalho relacionado 14 fornecido o controlo de acesso usando listas de acesso (ACLs). 2.2.2 Ceph O Ceph [47] é um sistema de ficheiros distribuı́do desenhado para ser fiável, disponı́vel, e com um alto desempenho ao mesmo tempo que é altamente escalável. Estas propriedades são alcançadas através das caracterı́sticas de desenho presentes na sua arquitectura onde a principal ideia é separar a gestão dos metadados e dos dados. O sistema é assim composto por três diferentes componentes como mostra a figura 2.5: o cluster de OSDs (object store devices) que é responsável por armazenar os dados e os metadados; o cluster de servidores de metadados (MDS) que concretiza o espaço de nomes e que coordena a segurança, a consistência e a coerência do sistema; e o cliente que executa operações de metadados nos MDSs e armazena os dados comunicando directamente com os OSDs. Figura 2.5: Arquitectura do Ceph [47]. Os OSDs oferecem grande escalabilidade pois disponibilizam uma interface para armazenamento de objectos. Esta permite a escrita e a leitura de intervalos muito maiores, e com tamanho variáveis, de bytes, do que a tradicional interface ao nı́vel do bloco. Estes utilizam um sistema de ficheiros local especial para armazenar os dados no disco. O cluster de MDSs baseia-se numa estratégia de partição dinâmica de sub-árvores que distribui hierarquicamente os metadados pelo diferentes nós MDS, permitindo adaptar-se aos diferentes tipos de carga de trabalho que está presentes nos sistemas de ficheiros. Embora estes servidores respondam aos clientes maioritariamente usando os metadados em cache, armazenam os seus nós de metadados nos OSDs. Estes servidores são também responsáveis por efectuar controlo de acesso aos ficheiros. Os clientes efectuam operações de escrita e leitura no cluster de OSDs e tanto o podem efectuar comunicando directamente com os Capı́tulo 2. Trabalho relacionado 15 OSDs ou através de um sistema de ficheiros implementado a nı́vel do utilizador através do FUSE [7]. Os clientes mantém uma cache local para aumentar a performance das operações de escrita e leitura. Esta cache é invalidade pelos MDSs na existência de múltiplos escritores ou de um conjunto de escritores e leitores para o mesmo ficheiro. Neste cenário, o cliente que adquirir o lock do ficheiro é obrigado a efectuar escritas sı́ncronas para os OSDs. Contudo, os cliente podem também efectuar escritas assı́ncronas se utilizarem um serviço de locks que os OSDs disponibilizam onde os clientes podem aceder exclusivamente a um determinado OSD. O Ceph, para mapear os objectos pelo diferentes OSDs disponı́veis, recorre a uma função de dados distribuı́da, chamada CRUSH [46], que elimina a preocupação com listas distribuı́das que mantenham a localização (OSD) dos dados. Os objectos armazenados pelos diferentes OSDs chamam-se placement groups (PGs), onde cada um é composto por diferentes blocos de diferentes ficheiros. Estes diferentes blocos de diferentes ficheiros são mapeados para dentro de cada PGs através uma função de hash. Para manter os dados sempre disponı́veis, o sistema replica os PGs por uma lista de n OSDs. A replicação é feita da seguinte forma: os pedidos de escrita são efectuados ao primeiro OSD disponı́vel da lista (chamado primary); este actualiza a versão do PG que recebe o novo bloco a escrever, e envia a escrita aos restantes OSDs (replicas) que mantém este PG. Os clientes recebem um ack quando os dados atingem o buffer de todas as réplicas (quando fica visı́vel aos outros clientes) e da mesmo forma, um commit quando a escrita é armazenada em memória estável por todas as réplicas. Na ocorrência do ack o sistema tolera a falha de um único OSD presente na lista, enquanto que no commit o cliente tem a garantia que mesmo que todos os OSDs da lista falhem, os dados podem ser recuperados. O Ceph mantém também um sistema de detecção de falhas de OSDs que permite perceber se as listas de OSDs para cada PG está disponı́vel. Quando algum OSD é dado como não disponı́vel, outro é adicionado à lista para permitir o mesmo nı́vel de replicação. 2.2.3 CODA O Coda [41] é um sistema de ficheiros cujo objectivo é manter a disponibilidade mesmo com clientes móveis, isto é, com conexão intermitente. A sua construção foi baseada no Andrew File System onde as caracterı́sticas que mantém deste são: o modelo, onde servidores confiáveis armazenam dados provenientes de estação de trabalho Unix não confiáveis; os clientes continuam a fazer cache de ficheiros inteiros e a guardar informação sobre onde os seus dados estão armazenados; usa também callbacks (promessa do envio de uma notificação aquando de uma alteração a qualquer ficheiro) para assegurar a coerência da cache nas diferentes estações, mas de uma forma mais complexa; utiliza réplicas só de leitura; e para assegurar segurança utiliza um protocolo de autenticação Capı́tulo 2. Trabalho relacionado 16 baseado em tokens e cifra todas as mensagens trocadas. Este sistema fornece uma disponibilidade mais alta que o AFS porque lida com falhas quer dos servidores, como da rede. Para tal são usadas duas estratégias complementares. A primeira é o facto de replicar os dados por diferentes servidores. A segunda prende-se na possibilidade que os clientes têm em fazer operações desconectados, ou seja, mesmo sem acesso à rede, estes podem continuar a operar na cache local. Para tal ser possı́vel, o Coda lida com falhas na rede usando uma estratégia optimista que assegura que depois de ocorrer uma partição, todos os conflitos irão ser detectados e resolvidos. A colecção de servidores que armazenam os dados (a unidade de replicação é chamada volume e representa um conjuntos de ficheiros e/ou directorias) é denominada de volume stompe group (VSG). Cada cliente mantém um subconjunto do VSG denominado accessible volume stompe group (AVSG) que são os membros do VSG disponı́veis, isto é, acessı́veis, no momento. Para replicar os dados é utlizado uma variante da abordagem read-one, write-all1 . A leitura é efectuada de um servidor previamente marcado como servidor preferido, contudo, é necessário contactar também os outros servidores do AVSG para assegurar que o servidor preferido têm a versão mais actual dos dados. Quando é encontrado um servidor com uma versão mais actual que o servidor preferido, este é marcado como novo servidor preferido e é estabelecida uma callback com ele. Já na operação de escrita, depois do ficheiro ser fechado, ele é replicado por todos servidores pertencentes ao AVSG em paralelo. Para manter a coerência da cache, as estações de trabalho que executam o sistema de ficheiros têm que detectar 3 tipos de acontecimentos no máximo t segundos depois de terem ocorrido. Assim, é necessário estar alerta para: • O aumento do AVSG (quando um servidor inacessı́vel se torna acessı́vel) tentando contactar os servidores que se encontram inacessı́veis, a cada t segundos. Quando este acontecimento se verifica, os clientes descartam as callbalcks dos objectos em cache, pois eles podem já não ser a versão mais actualizada; • A diminuição do AVSG (quando um servidor acessı́vel se torna inacessı́vel) testando a cada t segundos se todos os membros do AVGS se mantêm acessı́veis. Se o servidor preferido se tornar inacessı́vel, as callbacks desse servidor são descartadas; • A perda de callbacks simplesmente esperando callbacks dos servidores. As operações desconectadas começam assim que todos os membros do VSG se tornam inacessı́veis. A troca do modo de operação normal (replicação) para o modo de operação desconectado e o contrário é completamente transparente para o cliente excepto quando algum ficheiro em cache é perdido (o que acontece raramente). Obviamente, durante este modo, os clientes armazenam os dados na sua cache local. Quando os 1 Cada operação de escrita é efectuada em todos os servidores e a operação de leitura obtém os dados só de um. Capı́tulo 2. Trabalho relacionado 17 clientes conseguem aceder novamente a alguns membros do VSG é iniciado um processo de reintegração onde são executados um conjunto de actualizações a todos os membros do AVSG de forma a todas as réplicas ficarem iguais à cache local. 2.2.4 Frangipani O Frangipani [43] é um sistema de ficheiros distribuı́dos que fornece quase as mesmas garantias semânticas que os sistemas de ficheiros Unix. A figura 2.6 apresenta a arquitectura do Frangipani. Como podemos ver a sua estrutura é dividida em duas camadas. A camada de baixo contém dois serviços: o Petal (serviço de armazenamento descrito anteriormente) e um serviço de lock distribuı́do. O Petal ajuda o Frangipani a fornecer uma fácil administração, escalabilidade e tolerância a faltas. Estes dois serviços (Petal e lock) não necessitam estar na mesma máquina, até porque não trocam qualquer tipo de informação entre si. Na camada de cima encontram-se os clientes e os servidores de ficheiros Frangipani. Os clientes (programas do utilizador) acedem ao Frangipani através de uma interface padrão de chamadas ao sistema. Figura 2.6: Arquitectura do Frangipani [43]. Os servidores de ficheiros Frangipani comunicam com o Petal e com o serviço de lock. Para comunicar com o Petal, os servidores usam uma driver de dispositivo. Esta driver vê o Petal como um disco virtual com 264 bytes de espaço e esconde a real natureza distribuı́da presente na sua arquitectura fı́sica. Neste disco virtual é definido previamente espaço para logs, para inodes, para blocos pequenos e para blocos grandes. Capı́tulo 2. Trabalho relacionado 18 O sistema permite a adição e remoção de servidores recorrendo a poucas tarefas de administração (o sistema adapta-se ao novo número de servidores automaticamente). Para a recuperação após uma falha de um servidor (fail recovery) é usado write-ahead logging de metadados no Petal. Como não é feito log dos blocos de dados, os clientes não têm garantias de consistência depois de uma recuperação. Para manter sincronização quando diferentes clientes requisitam o mesmo bloco de dados, o Frangipani utiliza o modelo de lock multi-reader/single-writer. Os locks são efectuados a ficheiros inteiros ou directorias ao contrário de blocos individuais. A cache foi implementada seguindo a ideia da cache do AFS, mas neste caso cada servidor Frangipani envia uma notificação aos outros servidores para actualizarem a sua cache. Numa operação de escrita, só é garantido que os blocos de dados alcancem memória não volátil quando duas chamadas especı́ficas ao sistema são executadas - fsync ou sync. Como o Petal, o Frangipani permite também tirar snapshots ao sistema para a manutenção de backups. Estas snapshots são crash-consistent, o que significa que são uma imagem coerente do sistema. 2.2.5 Considerações Finais Desta secção podemos retirar muitas ideias para aplicar na construção do C2FS. Como podemos verificar, a utilização de cache no lado do cliente é essencial para o bom desempenho de um sistema de ficheiros. Outra interessante estratégia introduzida pelo AFS [40] é a transferência de ficheiros completos para os servidores de armazenamento. Isto permite alcançar um bom desempenho do sistema pois elimina a necessidade lidar com latências inerentes à transferência de blocos de dados individualmente. Por sua vez, o Ceph [47] utiliza a ideia da separação do tratamento de metadados com o armazenamento dos dados para o aumento do desempenho e da escalabilidade. Esta ideia é também bastante interessante pois uma vez que os sistema de ficheiros efectuam muito mais operações nos metadados do que nos dados, e as operações de dados por norma são mais lentas que as de metadados, a distribuição da carga de trabalho é bem conseguida. Por fim é importante dar ênfase as garantias de consistência de cache expostas pelo AFS e pelo Frangipani onde só é garantido que os dados sejam devidamente armazenados em memória estável após o seu fecho ou aquando das operações fsync ou sync. Contudo, é importante referir que todas as propostas de validação de cache apresentadas por estes necessitam computação nos servidores de armazenamento, o que não se verifica no C2FS. 2.3 Sistemas de Ficheiros para Clouds Nesta secção são apresentados alguns dos sistemas de ficheiros que armazenam os seus dados nos diferentes provedores de armazenamento. A figura 2.7 demonstra a arquitectura Capı́tulo 2. Trabalho relacionado 19 que estes sistemas de ficheiros adoptam. Alguns destes sistema utilizam uma proxy a que os clientes se conectam, e esta por sua vez é que contacta a cloud. Note-se que neste caso, a proxy é um ponto único de falha. Outros são executados directamente na máquina do cliente, conectando-se assim directamente à cloud. A comunicação existente entre os clientes e as clouds é efectuado via APIs fornecidas por estas. A utilização de clouds para armazenar os dados, ao contrário dos sistemas de ficheiros descritos anteriormente, tem a vantagem de fornecer um espaço de armazenamento quase ilimitado (ou mesmo ilimitado) enquanto que o custo não é muito elevado. Figura 2.7: Arquitectura de Sistemas de Ficheiros para clouds. 2.3.1 S3FS O S3FS [16] é um sistema de ficheiros para sistemas Unix que permite montar um bucket da Amazon S3 [4] como um sistema de ficheiros local através do FUSE [7]. Este sistema permite o uso de uma cache local efectuada em disco de forma a aumentar o desempenho do sistema. Note-se que esta cache só é utilizada se o cliente o indicar. Quando um ficheiro é aberto, é feita a transferência do ficheiro completo para a cache, e quando é fechado, é enviado para a cloud, efectuando assim todas as operações de escrita e leitura localmente. Quando uma transferência para a cloud não é efectuada com sucesso, o sistema volta a tentar mais 2 vezes antes de abortar a mesma. De forma a minimizar as transferência de dados da Amazon S3, são usados resumos criptográficos (computados através da técnica MD5) para validar a cache. Esta cache pode crescer infinitamente, podendo assim ocupar todo o espaço em disco. Se tal acontecer, é da responsabilidade do cliente eliminar os ficheiros de forma ao espaço do disco não ficar todo preenchido. É mantida também uma cache em memória (por omissão 4MB) para armazenar os metadados dos ficheiros. Capı́tulo 2. Trabalho relacionado 2.3.2 20 S3QL O S3QL [17] é um sistema de ficheiro para sistemas operativos tipo Unix que armazena os seus dados em provedores de armazenamento como Google Storage [9], e Amazon S3 [4]. Este sistema utiliza uma base de dados local que serve de cache tanto para dados como para metadados. Todas as operações, como a criação de uma directoria, a renomeação de um ficheiro, a alteração de permissões, são efectuadas nesta cache. Estas alterações são enviadas assincronamente para a cloud. Os ficheiros presentes no sistema de ficheiros são divididos e armazenados em blocos pequenos. Esta opção permite optimizar o desempenho e o custo associado à transferência dos dados para a cloud pois só os blocos requisitados/modificados necessitam ser obtidos ou enviados tanto da/para a cache, como da/para a cloud. Antes da transferência dos dados para a cloud, este passam primeiro por um mecanismo de compressão (como LZMA ou bzip2) e posteriormente são cifrados através da técnica AES com um chave de 256 bits. Para manter a integridade dos dados armazenados nas clouds o serviço armazena também um resumo criptográfico (usado SHA256 HMAC) para cada bloco de dados transferido. Uma outra caracterı́stica interessante do S3QL é que ele a geração snapshots de directorias servindo estas para backup. 2.3.3 BlueSky O BlueSky [45] é um sistema de ficheiros que foi principalmente desenhado para ser utilizado por clientes dentro de empresas. Para tal, o sistema adopta um arquitectura baseada no conceito de proxy. Os clientes comunicam assim com a proxy, que por sua vez interage directamente com a cloud para armazenar os dados. A comunicação feita entre os clientes e a proxy pode ser efectuada através de dois diferentes protocolos de sistemas de ficheiros do modelo cliente-servidor: o NFS (versão 3) e o CIFS. A proxy concretiza uma cache write-back usando o seu disco local, computando assim quase todos os pedidos localmente. Devido a isto, deve ser instalada na rede dos clientes para minimizar a latência inerentes aos pedidos. Os pedidos são assim todos satisfeitos na cache (pedidos de leitura e escrita) com a excepção da eventualidade de um pedido de leitura ser efectuado sobre um ficheiro que não está em cache. Neste caso o ficheiro é obtido da cloud e armazenado na cache. Quando a cache está cheia (visto a cloud ter mais capacidade que o disco local) os ficheiros são substituı́dos através de polı́ticas LRU (Least Recently Used). Os ficheiros são mantidos em cache divididos em blocos sequencialmente numerados onde cada bloco tem o tamanho de poucos megabytes. Isto permite melhorar a performance do sistema, pois só são lidos do disco os blocos referentes ao offset requisitado. Todas as escritas para as clouds são efectuadas assincronamente. Inerente a esta opção, existe o problema da possibilidade da falha do disco local. Se tal acontecer, Capı́tulo 2. Trabalho relacionado 21 poderão haver dados que serão perdidos, e consequentemente nunca propagados para a cloud. Para minimizar este risco, o BlueSky envia dados para as clouds a cada cinco segundos. Note-se que se um envio demorar mais que cinco segundos, o envio posterior só iniciará quando este terminar. O sistema adopta uma estrutura baseada em log, sendo este log a unidade de armazenamento utilizada. Cada log armazenado na cloud é composto por vários segmentos de log, e cada um deste segmentos de log agrega múltiplos objectos. Os logs são construı́dos de forma a terem um tamanho de aproximadamente 4MB (para esconder a latência inerente a efectuar escritas para a cloud com um tamanho pequeno). Note-se o sistema permite efectuar leituras parciais nestes logs armazenados na cloud. O sistema armazena quatro tipos diferentes de objectos nos logs. Estes objectos representam tando os dados como os metadados e podem ser blocos de dados, inodes, mapas de inodes e checkpoints. Os blocos de dados representam os próprios dados e cada um tem o tamanho fixo de 32KB (excepto o último bloco de um ficheiro que pode ser mais pequeno). Os inodes representam os metadados dos ficheiros contento informações sobre o dono do ficheiro, listas de controlo de acesso, timestamp e os apontadores para cada bloco de dados. Os mapas de inodes são utilizados para localizar as versões mais recentes de cada inode dentro do segmento. Por fim, os checkpoints contêm os apontadores para a localização do mapas de inodes em uso. Os checkpoints são também utilizados para manter a integridade do sistema após uma falha da proxy e para fornecer backups por versão. Para manter a confidencialidade dos dados, cada objecto é cifrado individualmente antes do seu envio para a cloud (através da técnica AES) e protegidos com códigos de autenticação de mensagens (com HMAC-SHA-256). Para limpar os dados não mais necessários presentes na estrutura em log armazenada na cloud, o BlueSky implementa um colector de lixo. Este colector de lixo tanto pode ser executado na proxy como numa instância de computação nas clouds (Amazon EC2 por exemplo), sendo neste último caso mais eficiente em relação aos custo e a performance. 2.3.4 Frugal cloud File System O Frugal cloud File System (FCFS) [36] é um sistema de ficheiros que foi concretizado tendo em conta o objectivo de reduzir ao máximo os custos monetários impostos por estes serviço relativos ao armazenamento e acesso aos dados. Para efectuar esta melhoria nos custos necessários para manter os dados nas clouds, o FCFS baseia-se nas diferentes opções de armazenamento que as algumas clouds fornecem que diferem não só nos custos, mas também no tempo de resposta aos pedidos. A Amazon por exemplo, fornece três diferentes opções de armazenamento: a Amazon S3 [4], a Amazon EBS [1] e a Amazon Elasticache [3]. A Amazon S3 fornece baixo custo de armazenamento, contudo, tem a desvantagem de cada pedido ter um preço associado (es- Capı́tulo 2. Trabalho relacionado 22 crita ou leitura, e no caso das leituras existe também um preço associado à quantidade de GB lidos) e as respostas a esses pedidos sofrerem de uma latência maior. Já a Amazon EBS fornece um custo para escritas e leituras mais baixo, mas o preço de armazenamento é mais elevado em relação à Amazon S3. A última opção referida, a Amazon Elasticache, é a que fornece o melhor tempo de resposta (mantém os dados em memória) não cobrando nada pelos pedidos nem pela quantidade de GB lidos, contudo o preço de armazenar os dados é muito mais elevado do que nas outras duas opções. Basicamente, quanto maior for o preço do armazenamento dos dados, menores serão os preços associados aos pedidos e quantidades de bytes transferidos, e menor a latência nos pedidos. Note-se que a Elasticache e a EBS não podem ser acedidos de foram da Amazon, o que implica que o FCFS só possa ser executado nas VMs (virtual machines) da Amazon EC2 [2]. O FCFS utiliza assim a Amazon S3 como disco do sistema (onde o armazenamento dos dados é mais barato) e a Amazon EBS ou Amazon Elasticache como cache (onde obter os dados é mais barato). Os ficheiros são armazenados em blocos de dados de 4 MB. Estes blocos de dados podem ser obtidos directamente do disco ou da cache. Neste último caso os blocos de dados têm de ter sido previamente transferidos do disco. Esta transferência (do disco para a cache) tem um preço associado se as suas bases de dados (S3 e EBS/Elasticache) estiverem em servidores diferentes. Note-se que quando os blocos de dados são carregados para a cache não são eliminados do disco devido a motivos de disponibilidade. Por omissão, os dados são armazenado no disco pelo simples motivo do preço de armazenamento ser mais baixo. Os blocos de dados, quando armazenados na cache, são mantidos dentro de volumes de armazenamento que podem ser ajustáveis a qualquer instante, de modo a terem exactamente a capacidade de armazenar os blocos que, para esse instante, são precisos manter em cache. A troca de ficheiros em cache é efectuada através de polı́ticas de substituição de cache do tipo LRU e ARC [31]. 2.3.5 Cumulus O Cumulus [44] é um sistema que permite aos utilizador fazerem backup dos seus sistemas de ficheiros através de snapshots. Apesar de este sistema não ser um sistema de ficheiros, está inserido nesta secção porque os backups que este permite efectuar sobre os sistemas de ficheiros são armazenados na cloud. A interface fornecida para os clientes comunicarem com o servidor consiste em somente 4 operações: get, put, list e delete. Estas operações operam em ficheiros inteiros. Como os sistemas de ficheiros têm muitos ficheiros pequenos, e armazená-los individualmente nas clouds trás alguns problemas como maiores tempos de latência e custos monetários mais elevados devido aos modelos de custos apresentados pelas clouds, o Cumulus agrupa vários ficheiros pequenos e coloca-os dentro de uma unidade denominada segmentos. Estas unidades são armazenadas da mesma forma que os ficheiros possuindo também um identificador único. Capı́tulo 2. Trabalho relacionado 23 Cada snapshot inclui um log de metadados e os próprios dados. O log de metadados contém entradas para cada ficheiro, onde são guardadas informações sobre as permissões e custódia do ficheiros, um resumo criptográfico para garantir a integridade dos dados, e os apontadores para a localização dos dados. Cada snapshot é transformada num segmento, comprimida e encriptada antes de ser enviada para a cloud. Os clientes podem fazer uma recuperação completa extraindo todos os ficheiros ou uma recuperação parcial recuperando só parte deles. 2.3.6 Considerações Finais Após o estudo destes sistemas de ficheiros para cloud, é importante dar relevância a três importantes limitações que estes apresentam. A primeira limitação refere-se ao caso dos sistema que adoptam uma arquitectura baseada em proxy, pois esta é um ponto único de falha. A segunda relata com o facto de nenhum deles permitir a partilha de ficheiros controlada por diferentes utilizadores em diferentes localizações (note-se que no caso de uma arquitectura com proxy é permitida a partilhar de ficheiros entre os clientes que a estejam conectados à mesma proxy). Por último, estes só confiam unicamente num provedor de armazenamento dependendo assim deste, não efectuando assim nenhuma replicação de dados. Apesar destas limitações, é de notar o mecanismo de validação de cache que alguns descrevem, em que são comparados resumos criptográficos efectuados para cada versão. 2.4 Considerações Finais Neste capı́tulo foram introduzidos e descritos alguns dos serviço de armazenamento, sistemas de ficheiros distribuı́dos e sistemas de ficheiros para clouds estudados que nos ajudaram a desenhar e concretizar o C2FS. No próximo capı́tulo é introduzida a arquitectura e modelo de sistema do C2FS, e é descrito em pormenor o serviço de armazenamento concretizado para este. Capı́tulo 2. Trabalho relacionado 24 Capı́tulo 3 Armazenamento de Dados do C2FS 3.1 C2FS Conforme já mencionado, o trabalho desenvolvido neste PEI enquadra-se num projecto maior que é um sistema de ficheiros que armazena os seus dados na cloud-of-clouds chamado C2FS (cloud-of-clouds file system). Assim nesta secção é introduzida a arquitectura e o modelo de sistema do C2FS para melhor se perceber a descrição dos componentes realizados por este projecto nas secções seguintes. 3.1.1 Arquitectura A figura 3.1 apresenta a arquitectura do C2FS. Na base na arquitectura está o FUSE-J [8]. Este é o componente responsável por interceptar as chamadas de sistema para recursos pertencentes ao C2FS. É também devido ao uso deste módulo que o C2FS fornece aos seus clientes uma interface do estilo POSIX [13]. As chamadas de sistemas interceptadas são passadas ao agente C2FS pois este implementa uma interface fornecida pelo FUSEJ. O agente C2FS concretiza assim uma lista de operações de sistemas de ficheiros (i.e., open, write, etc) onde integra os outros componentes do sistema: o serviço de directorias, o serviço de locks e o serviço de armazenamento. Note-se que a interacção com estes sistemas depende da operação recebida pelo agente C2FS, tendo cada operação um comportamento especı́fico. Além desta integração, o agente C2FS é também responsável por gerar a chave de encriptação para cada ficheiro. Na secção 3.2 é explicado em pormenor o funcionamento do FUSE-J e as operações de sistemas de ficheiros que este permite implementar. O serviço de directorias [32] é o componente responsável por armazenar os metadados dos recursos do C2FS. Juntamente com os metadados, é também armazenada a chave de encriptação. Este mecanismo faz também controlo de acesso a ficheiros partilhados. Estas funções são concretizadas tendo por base um serviço de coordenação distribuı́do chamado DepSpace [20] que é executado em diferentes provedores de computação, fazendo uso do conceito cloud-of-clouds, assim como o DepSky. Este componente faz uso de um sistema 25 Capı́tulo 3. Armazenamento de Dados do C2FS 26 de cache para diminuir o número de chamadas ao DepSpace, diminuindo assim também os custos associados a estas chamadas, e aumentando a performance do sistema. O serviço de locks [32] tem a tarefa de manter a consistência dos ficheiros controlando o acesso em simultâneo aos mesmos. Assim, o C2FS garante que enquanto um utilizador está a escrever num determinado ficheiro, mais nenhum outro pode efectuar esta mesma operação. Como o serviço de directorias, este serviço também é cliente do DepSpace. O serviço de armazenamento tem o objectivo de gerir os dados na cloud-of-clouds através do DepSky. Este componente fornece dois nı́veis distintos de cache. No primeiro os dados são mantidos no disco local para evitar chamadas às clouds, enquanto que no segundo, os dados são mantidos em memória de forma a diminuir o tempo de resposta, aumentando assim o desempenho do sistema. Este serviço permite também duas formas distintas de escrever os dados nas clouds. No primeiro as escritas são efectuadas de forma sı́ncrona enquanto que no segundo são efectuadas de forma assı́ncrona. Neste caso é mantida uma fila de tarefas a correr em background para gerir estas mesmas escritas. Os dados são encriptados antes do envio para as clouds, ou seja, os dados em cache estão em claro. Este serviço é descrito em detalhe na secção 3.4. Figura 3.1: Arquitectura do C2FS. 3.1.2 Modelo do Sistema Antes de descrevermos o serviço de armazenamento do C2FS em detalhe, explicamos as hipóteses que o sistema requer para um correcto funcionamento. Capı́tulo 3. Armazenamento de Dados do C2FS 27 Em primeiro lugar o C2FS tolera um número ilimitado de clientes assumindo que cada um destes tem um identificador único, e assume que a média do tamanho máximo por ficheiro é de 50MBs para garantir bom desempenhos. Em segundo lugar, o modelo de sistema do C2FS herda as propriedades dos modelos de sistema do DepSky e do DepSpace uma vez que o serviço de armazenamento do C2FS recorre ao DepSky para armazenar os dados na nuvem composta por uma cloud-of-clouds enquanto que os serviços de directorias e locks utilizam o DepSpace para armazenar os metadados. Cada cloud utilizada pelo DepSky representa um servidor passivo ou seja, que não é capaz de executar código nenhum da aplicação, fornecendo só uma interface para proceder a operações de escrita ou leitura de dados. Estas operações têm uma semântica de consistência regular onde uma operação de leitura que seja executada concorrentemente com uma operação de escrita irá retornar ou os dados que já lá estavam, ou os dados resultante da escrita em processo. Embora, como referido acima, o C2FS tenha a preocupação de não permitir mais que um escritor para o mesmo ficheiro no mesmo instante, o sistema não considera escritores maliciosos, pois estes ao terem acesso aos ficheiros, poderiam escrever dados sem sentido do ponto de vista da aplicação. A comunicação existente entre o DepSky e as clouds é efectuada via o modelo clássico de chamada remota a procedimentos (RPC). Cada operação continua a ser invocada até obter uma resposta da cloud ou até ser cancelada. Já a comunicação existente entre os serviço de directorias e locks com os servidores DepSpace é efectuada através de canais fiáveis autenticados ponto-a-ponto através do uso de sockets TCP e códigos de autenticação de mensagens (MAC) com chaves de sessão sobre a assunção que a rede pode perder, corromper ou atrasar mensagens, mas não o pode fazer infinitamente entre processos correctos. Para garantir que todas os servidores executam as mesmas operações por ordem, é usada uma primitiva de multicast com ordem total, baseada no protocolo de consenso Paxos Bizantino [42]. Tal protocolo requer um modelo de sistema eventualmente sı́ncrono. Tanto as clouds que são os servidores de armazenamento, como os servidores do DepSpace que mantem os metadados online, toleram faltas bizantinas [30] utilizando sistemas de quóruns bizantinos onde são requeridos n ≥ 3f + 1 para suportar f servidores faltosos. Contudo, o sistema tolera um número ilimitado de clientes faltosos. 3.2 FUSE O FUSE (File system in USEr space) [7] é um módulo para Linux que permite a construção de sistemas de ficheiros no espaço do utilizador, eliminando assim a necessidade de efectuar modificações a nı́vel do kernel. Isto significa que com a utilização deste módulo, o sistema de ficheiros não necessita ser executado no kernel pois é ex- Capı́tulo 3. Armazenamento de Dados do C2FS 28 ecutado a nı́vel do utilizador. Outra vantagem inerente à utilização deste módulo para a implementação do sistemas de ficheiros é a interface ao estilo POSIX [13] que é oferecida aos clientes, facilitando assim a gerência de ficheiros na cloud-of-clouds. A figura 3.2 ilustra como o FUSE interage com a arquitectura dos sistemas de ficheiros Unix. Quando o VFS (Virtual File System) intercepta uma chamada de sistema a um recurso pertencente ao sistema de ficheiros C2FS, automaticamente chama o módulo FUSE (FUSE). Este módulo é instalado no Kernel aquando da instalação do FUSE. Este por sua vez, envia a chamada para a biblioteca do FUSE (libfuse) através de um descritor de ficheiro especial. Por fim, o processo que concretiza o sistema de ficheiros recebe a chamada, processa-a, e envia a resposta pelo caminho inverso. Figura 3.2: Caminho percorrido por cada chamada ao sistema. Contudo, o FUSE é implementado em C enquanto que os sistemas a integrar no C2FS, o DepSky e o DepSpace, são implementados em Java, o que dificulta tal integração. É usado então uma concretização do FUSE em Java chamado FUSE-J [8] para facilitar a integração dos sistemas existentes. Este fornece uma API Java que usa ligações JNI (Java Native Interface) para comunicar com a biblioteca do FUSE. O FUSE-J fornece uma interface para implementar as operações de sistema de ficheiros chamada FileSystem3. A tabela 3.1 apresenta a lista das operações que esta interface permite implementar e a função de cada uma delas no sistemas de ficheiros FUSE-J. 3.3 DepSky Nesta secção são apresentadas as alterações que foram feitas no DepSky de modo a este responder de uma melhor forma às necessidades do C2FS. Em sumário foram feitas duas melhorias significativas, sendo elas a adição de um novo protocolo de uso e a adição de uma nova operação que permite ler versões antigas de uma determinada Data Unit. Em baixo são descritas estas duas alterações no DepSky. Capı́tulo 3. Armazenamento de Dados do C2FS 29 Operações Função getattr(path, getattrSetter) retorna os metadados para um determinado recurso. lista os recursos filhos de uma determinada directoria. criar uma directoria com as permissões fornecidas. criar um ficheiro com as permissões fornecidas. abre o descritor do ficheiro de acordo com o modo pretendido (e.g., O WRONLY, O RDWR). lê o número de bytes pedidos a partir do offset pretendido de um ficheiro aberto. escreve para um ficheiro aberto a partir do offset fornecido. renomeia um determinado recurso. muda as permissões de um determinado recurso. fecha o descritor de ficheiro assegurando que os dados em cache estão devidamente armazenados no disco. Note-se que se um ficheiro tiver mais que um descriptor associado (e.g., no caso de um fork), haverá mais que um flush por open. sincroniza os dados em cache de um determinado ficheiro aberto com o disco. cria uma ligação forte (hard link) entre os dois ficheiros. liberta um determinado ficheiro quando todos os descriptores desse ficheiro tiverem sido devidamente fechados (flush). altera o tamanho de um ficheiro. Pode ser invocada sobre ficheiro abertos ou ficheiros fechados elimina uma directoria. obtém informação estatı́sticas sobre o sistema de ficheiros. cria uma ligação simbólica para um dado recurso. lê uma ligação simbólica. elimina um ficheiro. muda o tempo de acesso e/ou o tempo de modificação de um ficheiro. muda o dono e o grupo do ficheiro. getdir(path, dirFiller) mkdir(path, mode) mknod(path, mode, rdev) open(path, flags, openSetter) read(path, fh, buf, offset) write(path, fh, isWritepage, buf, offset) rename(from, to) chmod(path, mode) flush(path, fh) fsync(path, fh, isDatasync) link(from, to) release(path, fh, flags) truncate(path, size) rmdir(path) statfs(statfsSetter) symlink(from, to) readlink(path, link) unlink(path) utime(path, atime, mtime) chown(path, uid, gid) Tabela 3.1: Operações FUSE-J. Capı́tulo 3. Armazenamento de Dados do C2FS 30 Modificação 1. Por motivos relacionados com o controlo de acesso sobre ficheiros partilhados, o serviço de armazenamento (um componente do C2FS descrito na secção seguinte) cifra os dados antes de os guardar nas clouds (usando o DepSky), sendo a chave simétrica usada para cifrar/decifrar os dados armazenada no serviço de directorias. Assim, os dados irão ser armazenados no DepSky já previamente cifrados. Como já descrito anteriormente, o DepSky fornece dois protocolos distintos para os clientes gerirem os seus dados na cloud-of-clouds: o DepSky-A e o DepSky-CA [19]. Contudo, nenhum destes protocolos responde devidamente à necessidade do C2FS. O DepSky-A não nos é útil porque, apesar de garantirmos a confidencialidade dos dados devido à sua cifração no serviço de armazenamento, se um bloco de dados de tamanho T for replicado em n clouds, irá ser consumido n × T espaço de armazenamento e os custos irão ser, em média, n vezes maiores do que se for usado só uma cloud. O DepSky-CA também não se revela óptimo para o C2FS porque, embora solucione o problema descrito anteriormente através do uso de códigos de apagamento, cifra também os dados e usa partilha de segredo para garantir confidencialidade das chaves, o que penaliza a performance uma vez que os dados são encriptados duas vezes, uma a nı́vel do C2FS, e outra no DepSky. Foi concretizado então um novo protocolo que não é mais que uma variante do DepSkyCA. A diferença é que não faz uso de técnicas criptográficas nem de partilha de segredos, mas mantém a disponibilidade e integridade dos dados ao mesmo tempo que reduz os custos monetários de armazenamento devido à utilização de códigos de apagamento na replicação dos dados. Assim, em cada operação de escrita, é armazenado em cada cloud um fragmento codificado (são gerados tantos fragmentos quanto o número de clouds utilizado). Na operação de leitura são necessários f + 1 fragmentos (em que f é o número de provedores que podem ser faltosos) para obter o bloco de dados inicial1 . Note-se que mesmo na eventualidade de alguém escutar a rede e obter f +1 fragmentos (isto é, o bloco inicial), não conseguirá obter os dados em claro pois estes são previamente cifrados pelo serviço de armazenamento do C2FS. Modificação 2. O DepSky mantém todas as versões de todas as escritas efectuadas em cada cloud. Neste cenário foi concretizada uma operação de leitura que permite ler uma versão antiga de uma unidade de dados do DepSky. A esta nova operação demos o nome readMatching(Du, h), onde o primeiro argumento é a unidades de dados do DepSky e o segundo é um resumo criptográfico. Assim o objectivo é ler a primeira versão em que o seu resumo é igual ao resumo fornecido. Para a concretização desta operação foram necessárias algumas alterações na operação de escrita do Depsky. Primeiro têm que ser armazenados todos os metadados referentes a cada versão escrita, ao invés de armazenar somente os metadados da última versão. Esta alteração foi efectuada de modo a garantirmos a integridade de todos os blocos de dados 1 Contudo são esperadas n − f respostas devido ao protocolo bizantino utilizado. Capı́tulo 3. Armazenamento de Dados do C2FS 31 escritos em cada cloud. Outra alteração feita foi a introdução de um novo campo nos metadados chamado datahash. Este campo armazena um resumo criptográfico efectuado pelo DepSky sobre cada bloco de dados completo a ser escrito (i.e., antes de passar por qualquer processo de codificação ou cifração). Por fim, a operação de escrita do DepSky passa a retornar ao cliente este resumo. O algoritmo desta nova alteração é bastante simples. • Primeiro é obtido o ficheiro de metadados referente à unidade de dados fornecida Du. Neste caso basta obter o ficheiro de metadados de n − f cloud (uma vez que neste conjunto de clouds existe pelo menos uma com a versão do campo datahash mais actual). • Depois são comparados os resumos presentes nos campos datahash com o resumo fornecido h, iniciando a procura na versão mais recente, até à mais antiga. • Quando encontrado um resumo igual ao resumo h, é lida das clouds a versão referente a esse resumo encontrado. Esta leitura é realizada seguindo o protocolo normal de leitura, ou seja, é efectuada num quórum de n − f clouds. Caso nenhum resumo presente no ficheiro de metadados seja igual ao resumo fornecido, é retornado erro na operação. Esta operação foi introduzida para satisfazer um mecanismo explicado na tese [32], que tem por finalidade minimizar uma importante limitação presente na maioria das clouds, que é a consistência eventual, fornecendo assim uma consistência regular forte para os ficheiros armazenados no C2FS. 3.4 Serviço de Armazenamento Nesta secção é apresentado o serviço de armazenamento concretizado para o C2FS. Como já referido anteriormente, este serviço utiliza o DepSky modificado descrito na primeira modificação da secção 3.3 que mantém a integridade e a disponibilidade dos dados armazenados na cloud-of-clouds. A confidencialidade é fornecidada pelo próprio serviço de armazenamento que cifra os dados antes do seu envio para as clouds. Cada ficheiro neste serviço está directamente relacionado com uma unidade de dados do DepSky (Data Unit). Este serviço dispõe de uma cache local que aumenta o desempenho do sistema de ficheiros e diminui os custos monetários associados a downloads que, desta forma, são evitados. Note-se que apesar de este serviço armazenar os dados nas clouds através do DepSky, é importante referir que só opera em dados que estejam em cache, sendo só necessário fazer o download dos dados das clouds caso exista uma versão mais recente destes nas clouds. Isto acontece se o ficheiro for partilhado por diferentes utilizadores Capı́tulo 3. Armazenamento de Dados do C2FS 32 ou se o mesmo utilizador mantiver o C2FS em diferentes estações de trabalho. Para dados que não sejam partilhados nunca é necessário efectuar uma leitura das clouds (a não ser que o mesmo utilizador monte o mesmo o sistema numa máquina diferente onde a cache não está actualizada), servindo estas só para backup. Isto é muito importante pois conseguimos poupar dinheiro uma vez que a transferência de dados para dentro da maioria das clouds não tem nenhum, ou quase nenhum preço associado, sendo apenas as operações de transferência de dados para fora cobradas. Por omissão, a cache dos dados é feita no disco local, mas, os utilizadores deste serviço podem também manter a cache dos dados em memória volátil de forma a diminuir o tempo de resposta para cada operação de leitura ou escrita. Este serviço disponibiliza também duas formas de enviar os dados para as clouds, sı́ncrona e assı́ncrona, em que na sı́ncrona os clientes esperam pela confirmação de que os dados estão devidamente armazenados, e na assı́ncrona o envio dos dados é feito em background. Assim, este serviço permite ao C2FS ser configurado de vários formas: • O nı́vel de cache a utilizar (só em memória fı́sica ou também em memória volátil). • A forma do envio-o dos dados para as clouds (sı́ncrona ou assı́ncrona). • Escolher se a operação fsync do agente C2FS sincroniza os dados no disco local ou na cloud-of-clouds. Note-se que consoante os parâmetros de configuração escolhidos diferentes nı́veis de consistência e durabilidade são fornecidos. De seguida serão descritos os algoritmos para as operações deste serviço, a sua integração no agente C2FS, e os diferentes nı́veis de consistência consoante os parâmetros de configuração. 3.4.1 Visão Geral da Gestão do Armazenamento Conforme já mencionado, o serviço de armazenamento concretizado para o C2FS faz um uso intensivo de cache. Logicamente esta cache ocupa muito espaço no disco local (que pode vir a ser o disco todo). Poderı́amos evitar isto concretizando um serviço de armazenamento que operasse directamente nos ficheiros armazenados nas clouds sem fazer cache dos dados. Mas com isto terı́amos muitos mais problemas do que benefı́cios no que diz respeito ao desempenho do sistema e aos custos associados às transferências de dados para as clouds. Note-se que, por exemplo, para uma operação de escrita com offset maior que zero ocorrer com sucesso, iria ser necessário uma leitura no DepSky (que realmente são duas leituras, uma para os metadados e outra para os dados [19]) para obter os dados, e depois de o blocos de dados final ser obtido (i.e., com a escrita já efectuada no offset correcto) iria ser necessário uma escrita no DepSky (que na verdade efectua uma leitura dos metadados, e duas escritas, uma para os dados, e outras para ou metadados) para armazenar o ficheiro já actualizado. Assim para uma operação de escrita no C2FS terı́amos Capı́tulo 3. Armazenamento de Dados do C2FS 33 cinco acessos à cloud-of-clouds. Ora, sobre um ficheiro, desde o momento que é aberto (open) até ao momento que é fechado (close), podem ocorrer inúmeras operações de escrita com offsets diferentes, o que provocaria um desempenho completamente inaceitável conjugado com preços proibitivos. Assim, a cache que o serviço de armazenamento faz sobre os ficheiros é um dos pontos cruciais para o bom desempenho do C2FS. Os ficheiros podem ser mantido em três diferentes localizações: em memória, em disco, e na cloud-of-clouds. A figura 3.3 ilustra o fluxo que os dados fazem enquanto são transferidos entre as diferentes localizações. As setas contı́nuas representam as escritas, enquanto que as setas a tracejado representam as leituras. Como podemos verificar, os clientes só efectuam leituras e escritas na memória volátil (se esta for utilizada). Da memória os dados são escritos para o disco, e posteriormente, do disco são escritos para as clouds. Como mostra a figura, não é permitido que os dados sejam escritos directamente da memória para as clouds. Isto não é permitido para no caso de ocorrer um falha durante o envio dos dados, estes poderem ser recuperados. Da mesma forma, quando obtidos os dados das clouds, estes são primeiro armazenados em disco, e só posteriormente em memória. As operações disponibilizadas para os clientes gerirem os dados nestas diferentes localizações são descritas em baixo. Figura 3.3: Fluxo dos dados. Tanto a cache em disco como a cache em memória aplicam politicas LRU (Least Recently Used) para a substituição de ficheiros quando não existe espaço suficiente para armazenar novos ficheiros. Basicamente quando é necessário espaço, são eliminados os ficheiros que há mais tempo não são acedidos. O tamanho máximo da cache em disco é exactamente o espaço do disco local, já o tamanho máximo da cache em memória é configurado pelo cliente. Note-se que antes da eliminação de ficheiros da memória, estes são armazenados devidamente em disco de forma a não se perder a versão mais actual. Os clientes podem manter os dados na cache em memória durante o tempo que desejarem. Isto significa que todas as alterações feitas sobre um ficheiro que está em memória não serão armazenadas em memória estável (disco local ou clouds-of-clouds) até o cliente o indicar ou até que seja necessária a sua substituição. Capı́tulo 3. Armazenamento de Dados do C2FS 3.4.2 34 Algoritmos de Gestão de Armazenamento Nesta secção são apresentadas as caracterı́sticas fundamentais do serviço de armazenamento como as variáveis utilizadaz e os algortimos concretizados. Para a validação da cache, o serviço de armazenamento mantém armazenados os resumos criptográficos retornados em cada escrita no DepSky (modificação 2 descrita na secção 3.3). Este resumo é fornecido ao serviço de directorias de forma a ser armazenado juntamente com os outros metadados do ficheiro. Assim o resumo presente no serviço de directorias é sempre o mais actual. A validação de cada ficheiro em cache é então efectuada comparando o resumo fornecido pelo serviço de directorias com o resumo armazenado neste serviço. Estes resumos criptográficos são mantidos e também frequentemente actualizados no disco local para evitar transferências das clouds depois do sistema ser desligado e ligado novamente. Este serviço mantém também a indicação de quais os ficheiros que foram alterados e que ainda não foram enviados para as clouds, de formar a efectuar envios desnecessários. Para possibilitar a recuperação após uma falha, ou seja, para sincronizar ficheiros que foram alterados e não chegaram a ser enviados para as clouds, esta informação é também mantida no disco local. Por último, é também mantido o tamanho dos dados de cada ficheiro. Estas informações são carregadas para memória sempre que o C2FS é montado. Este serviço foi concretizado também, tendo em conta que um dos objectivos do C2FS é fornecer um registo em que são aceites um cliente escritor e múltiplos clientes leitores para o mesmo ficheiro para cada instante. Para o serviço de armazenamento, este modelo obriga que a cada operação de leitura sobre um determinado ficheiro seja verificado se existe uma nova versão disponı́vel nas clouds, pois a qualquer momento da leitura, um cliente escritor pode actualizá-los. Já na operação de escrita não é necessária esta verificação pois o serviço de locks [32] garante que enquanto um cliente escritor efectua uma escrita, mais nenhum outro o pode fazer. Em baixo são apresentadas as operações que este serviço disponibiliza para os clientes gerirem os dados nas três diferentes localizações(memória, disco e cloud-of-clouds) e qual a funcionalidade de cada uma delas. Note-se que estas operações foram concretizadas tendo em conta a interface de sistemas de ficheiros que o agente C2FS implementa e o momento em que cada operação deste serviço é invocada é determinante para o seu bom funcionamento. Nos algoritmos em baixo, os resumos criptográficos estão representados na variável hashs, a informação referente ao ficheiros alterados em cache é armazenado na variável valueToSend e o tamanho dos dados na variável sizes. As variáveis cacheMemory e cacheDisk representam os acessos à memória e ao disco respectivamente. Por sua vez, a variável depsky representa os acessos efectuados ao DepSky. Capı́tulo 3. Armazenamento de Dados do C2FS 35 Operação Update Cache. Esta operação é responsável por ler os dados da cloud-ofclouds utilizando o DepSky. Como podemos verificar no algoritmo 1, os dados são lidos das clouds por dois motivos: ou os dados não se encontram em cache, ou os dados em cache estão desactualizados (linha 2). Os dados em cache não se encontram actualizados se o resumo fornecido pelo cliente do serviço for diferente do resumo mantido no serviço de armazenamento. Os dados são então lidos do DepSky usando a operação readMatching (modificação 2 da secção 3.3) como mostra a linha 5, que recebe como argumentos a unidade de dados referente ao ficheiro requerido (linha 3) e o resumo criptográfico referente à versão a obter. Como podemos ver no algoritmo, caso os dados não consigam ser obtidos das clouds, isto é, se não houver nenhuma versão nas clouds que diga respeito ao resumo fornecido, esta operação volta a tentar obter os dados mais três vezes, de cinco em cinco segundos (linhas 4-8). Isto acontece porque como referido anteriormente, o resumo fornecido pelo cliente, no caso o agente C2FS, é sempre o mais actual, e por conseguinte, isto significa que os dados referentes a este resumo já foram escritos para as clouds (operação Sync W Clouds). Os dados podem não estar logo visı́veis após a sua escrita nas clouds devido à consistência fraca fornecida por estes2 . Devido a isto, a sua leitura é tentada três vezes. Note-se que caso os dados não sejam obtidos em nenhuma das tentativas é retornado erro ao cliente (linhas 9-10). Caso os dados sejam obtidos, são então decifrados utilizando a chave simétrica fornecida pelo cliente (linha 11) e a cache é revalidada, isto é, os dados obtidos são colocados em cache a partir do offset 0, e é escrito em disco o novo resumo, a informação de que o ficheiro neste momento está actualizado e o tamanho dos dados lidos (linhas 12-16). Posteriormente, caso o cliente esteja a usufruir da memória volátil, os dados são adicionados a esta (linhas 17-20). Note que no caso de não ter sido necessário efectuar a leitura das clouds, para escrever os dados em memória, estes tem que ser obtidos do disco (neste caso a partir do offset 0 e indicando que se quer ler o ficheiro todo). Esta operação é responsável por esta acção para garantirmos que sempre que um cliente desejar adicionar um ficheiro a este nı́vel de memória, adiciona a versão mais actual do ficheiro. Esta operação é chamada pelo agente C2FS na operação open ao contrário do que seria suposto. Embora a operação open seja considerada uma operação de metadados, a leitura dos dados das clouds é feita nesta operação para que todas as operações efectuadas sobre um ficheiro aberto (write, read, fsync e flush) sejam feitas sobre um ficheiro actualizado. Operação Write Data. Esta operação tem a função de escrever os dados para o disco local ou para a memória. O algoritmo 2 mostra-nos como a operação é concretizada. Como podemos ver, caso o serviço de armazenamento esteja a usufruir da cache em memória volátil (linha 2), a referência dos dados é obtida desta (linha 3). De seguida é verificado 2 [4]. Note-se que no caso da Amazon S3, os dados estão visı́veis num tempo aproximado a cinco segundos Capı́tulo 3. Armazenamento de Dados do C2FS 36 Algorithm 1: Update Cache Map h String, byte[] i hashs; Map h String, boolean i valueToSend; Map h String, int i sizes; CacheOnDiskManager cacheDisk; CacheOnMemoryManager cacheMemory; DepSky depSky; 1 2 3 4 5 6 7 8 Entrada: name - identificador do ficheiro, key - chave para desencriptar os dados, hash - resumo criptográfico para verificar se os dados está em cache estão actualizados Saı́da: nenhuma inı́cio se (name ∈ / cacheDisk || hash 6= hashs.get(name)) então dataU nit ←− DataU nit(name); para (0 ≤ i ≤ 3) faça cipherdata ←− depsky.readM atching(dataU nit, hash); se (cipherdata 6= null) então sai do ciclo; senão sleep(5000ms); se (cipherdata = null) então retorna f alse; 9 10 data ←− decryptData(cipherdata, key); cacheDisk.writeData(name, data, 0); sizes.add(name, data.length); valueT oSend.add(name, f alse); hashs.add(name, hash); write to disk(name, hash, f alse, data.length); 11 12 13 14 15 16 se (cacheM emory 6= null) então se (data = null) então data ←− cacheDisk.getData(name, 0, sizes.get(name)); 17 18 19 cacheM emory.writeData(name, data, 0); retorna true; 20 fim se é necessário redimensionar o tamanho do buffer. Isto acontece se a soma do tamanho do bloco a escrever com a posição a iniciar a escrita for superior ao tamanho do buffer em cache (linha 4-5). O buffer é sempre redimensionado para o dobro do tamanho de forma a não ser necessário redimensionar o buffer e todas as operações de escrita. Por fim o ficheiro é marcado como alterado (linha 6) e os dados a escrever são colocado no buffer a partir no offset correcto. No caso de a escrita ser efectuada para disco, o ficheiro é marcado como alterado e esta informação é armazenado em disco (linhas 8-9) no momento Capı́tulo 3. Armazenamento de Dados do C2FS 37 antes de se proceder à escrita dos dados (linha 10). Esta ordem de operações permite que todos os ficheiros alterados sejam enviados para as clouds, mesmo na presença de uma falha após a sua escrita. Por fim é verificado se a escrita (quer em memória ou em disco) alterou o tamanho dos dados, e caso tenha alterado, é armazenado o novo tamanho (linhas 11-14). O tamanho do ficheiro é então retornado ao cliente. Logicamente esta operação é chamada pelo agente C2FS aquando de uma chamada ao sistema write. Esta operação irá escrever sempre sobre a versão mais actual dos dados, pois a chamada ao sistema write é só invocada sobre ficheiros abertos (isto é, depois de um open). Algorithm 2: Write Data Map h String, boolean i valueToSend; Map h String, int i sizes; CacheOnDiskManager cacheDisk; CacheOnMemoryManager cacheMemory; 1 2 3 4 5 Entrada: name - identificador do ficheiro, value - dados a escrever, offset posição de onde iniciar a escrita Saı́da: tamanho final dos dados inı́cio se (cacheM emory 6= null) então data ←− cacheM emory.readData(name); se (value.length + offset > data.length) então resizeBuf f er(data); valueT oSend.add(name, true); memcopy(data, offset, value, 0, value.length); senão valueT oSend.add(name, true); write to disk(name, true); cacheDisk.writeData(name, value, offset); 6 7 8 9 10 14 se (value.length + offset > sizes.get(name)) então size ←− value.length + offset; sizes.add(name, size); write to disk(name, size); 15 retorna sizes.get(name); 11 12 13 fim Operação Read Data. Esta operação é usada para ler um determinado ficheiro. Como podemos ver no algoritmo 3, a primeira preocupação da operação é verificar se os dados em cache para o ficheiro em questão estão actualizados através da chamada a operação já descrita em cima Update Cache (linha 2). Esta verificação em cada leitura vêm ao encontro do modelo de operação requerido pelo C2FS referido em cima (um escritor e Capı́tulo 3. Armazenamento de Dados do C2FS 38 múltiplos leitores). Se não for possı́vel obter os dados actualizados é retornado erro ao cliente. Após ter a garantia que os dados em cache estão devidamente actualizados, os dados são lidos através da memória volátil se esta estiver a ser utilizada e se o ficheiro estiver presente neste nı́vel, ou caso contrário são obtidos do disco (linhas 3-5). Por fim, os dados são requeridos são retornados ao cliente. Esta operação é invocada pelo agente C2FS na operação read. Algorithm 3: Read Data Map h String, byte[] i hashs; CacheOnDiskManager cacheDisk; CacheOnMemoryManager cacheMemory; 1 2 3 4 5 Entrada: name - identificador do ficheiro, key - chave para desencriptar os dados, hash - resumo criptográfico para verificar se os dados está em cache estão actualizados, offset - posição para iniciar a leitura, capacity número de bytes a ler Saı́da: valor do ficheiro lido inı́cio se (U pdate Cache(name, key, hash)) então se (cacheM emory 6= null && cacheM emory.contains(name)) então data ←− cacheM emory.readData(name, offset, capacity); senão data ←− cacheDisk.readData(name, offset, capacity); retorna data; 6 retorna null; 7 fim Operação Trunc Data. Esta operação tem o objectivo de alterar o tamanho de um determinado ficheiro. No algoritmo 4 podemos ver como a operação foi implementada. A primeira preocupação a ter e conta é a de ler os dados da cloud se os dados em cache não estiverem actualizados (linha 2). Caso a operação retorne erro, é também retornado erro ao cliente (linha 3). De seguida, os dados são truncados tanto em disco como em memória, caso esta esteja a ser utilizada (linhas 4-6). Posteriormente o ficheiro é armazenado tanto em memória como em disco o novo tamanho do ficheiro e a informação de que o ficheiro foi alterado. Por último, caso o cliente do serviço o obrigue, o ficheiro é enviado para as clouds (linhas 10-11). Esta operação é invocada na operação truncate do agente C2FS. Esta operação apresenta uma semântica diferente das operações anteriores (Write Data e Read Data) devido à especificação que o FUSE-J dá para esta chamada de sistema: a operação truncate pode ser invocada sobre um ficheiro fechado. Isto significa que os dados em cache podem não estar actualizados aquando da sua chamada e que pode não vir a ser invocada nen- Capı́tulo 3. Armazenamento de Dados do C2FS 39 huma operação de sincronização (fsync ou flush) após a alteração do tamanho do ficheiro. Dai a necessidade de garantirmos que a alteração é feita em todas as localizações onde o ficheiro se encontra. Note-se ainda que esta operação não é mais que uma escrita, e portanto o ficheiro deve ser bloqueado para escrita caso ainda não esteja (no caso do ficheiro estar fechado). Assim, o cliente do serviço, neste caso o agente C2FS, tem que ter a preocupação extra de verificar se o ficheiro já está bloqueado para escrita, e caso não esteja deve bloqueá-lo. Se o ficheiro não estiver bloqueado para escrita deve também obrigar a operação Trunc-Data a sincronizar os dados com as clouds especificando-o no argumento da operação toSyncWithClouds. Algorithm 4: Trunc Data Map h String, byte[] i hashs; Map h String, boolean i valueToSend; Map h String, int i sizes; CacheOnDiskManager cacheDisk; CacheOnMemoryManager cacheMemory; 1 2 3 Entrada: name - identificador do ficheiro, key - chave para desencriptar os dados, hash - resumo criptográfico para verificar se os dados está em cache estão actualizados, size - novo tamanho do ficheiro, toSyncW ithClouds - variável que diz à operação se é necessário sincronizar os dados com as clouds ou não Saı́da: nenhuma inı́cio se (U pdate Cache(name, key, hash)) então retorna f alse; cacheDisk.truncateData(name, size); se (cacheM emory 6= null && cacheM emory.contains(name)) então cacheM emory.truncateData(name, size); 4 5 6 11 sizes.add(name, size); valueT oSend.add(name, true); write to disk(name, true, size); se (toSyncW ithClouds = true) então Sync W Clouds(name, key); 12 retorna true; 7 8 9 10 fim Operação Sync W Disk. Esta operação tem a função de armazenar um determinado ficheiro presente na memória volátil no disco local. Como mostra o algoritmo 5 o ficheiro só é armazenado em disco se sofreu alguma alteração desde o momento que foi carregado para memória (linha 2). Caso se verifique isso, o ficheiro é obtido da memória (linha 3), depois é escrito em disco (linha 4), e por fim, é armazenado também em Capı́tulo 3. Armazenamento de Dados do C2FS 40 disco a informação de que o ficheiro em disco sofreu alterações de forma a possibilitar a recuperação após um falha. Esta operação é invocada pelo agente C2FS na operação fsync se o utilizador do C2FS apenas de desejar que a sincronização dos dados seja feita no disco local. Sincronizar os dados apenas no disco nesta chamada ao sistema pode significar um grande aumento da performance se, durante a abertura e o fecho de um ficheiro, a operação fsync for invocada muitas vezes. Note-se que se o cliente configurar o sistema para a operação fsync sincronizar os dados no disco e não estiver a utilizar a memória volátil, os dados já estarão previamente sincronizados, não sendo assim necessário nenhum acesso ao disco. Algorithm 5: Sync W Disk Map h String, int i sizes; CacheOnDiskManager cacheDisk; CacheOnMemoryManager cacheMemory; 1 2 3 4 5 Entrada: name - identificador do ficheiro Saı́da: nenhuma inı́cio se (cacheM emory 6= null && cacheM emory.contains(name) && valueT oSend.get(name) = true) então data ←− cacheM emory.readData(name, 0, sizes.get(name)); cacheDisk.writeData(name, data, 0); write to disk(valueT oSend); fim Operação Sync W Clouds. Esta operação é utilizada para sincronizar os dados com a cloud-of-clouds. O algoritmo 6 começa por efectuar uma chamada à operação Sync W Disk para garantir que os dados que irão ser armazenados nas clouds estão previamente armazenados no disco local (linha 2). Os dados só são então enviados para as clouds se sofrerem alguma alteração em cache (linha 6). Se não sofrerem qualquer alteração significa que estão iguais ao último download ou envio efectuado, ou seja, não é necessário enviá-los para as clouds. Antes de serem enviados, os dados são lidos do disco (linha 7) e depois são cifrados com a chave simétrica (linha 8) fornecida pelo cliente. Os dados são então enviados consoante o modelo utilizado (sı́ncrono ou assı́ncrono). Estes diferentes modelos são explicados em detalhe na secção 3.4.3. Em qualquer dos modelos, assim que o envio de dados para as clouds terminar é obtido o novo resumo criptográfico dos dados enviados (linha 6) retornado na operação de escrita do DepSky. O serviço de directorias é então notificado com este novo resumo e com o tamanho dos dados (linha 7). É necessário esta sincronização entre o serviço de directorias e o serviço de armazenamento para garantir que os metadados só serão actualizados depois dos dados o serem, de forma a que nunca nenhum cliente leia os metadados de um ficheiro que ainda não Capı́tulo 3. Armazenamento de Dados do C2FS 41 existe. Embora assim um cliente possa obter metadados de uma versão mais antiga aos dados que estão nas clouds, é muito menos provável que o contrário descrito em cima, pois uma escrita nos servidores de metadados [32] é muito mais rápida que uma escrita nos servidores de armazenamento. Por fim o novo resumo criptográfico é armazenado substituindo o antigo, o ficheiro é transferido do estado de alterado para actualizado, e as estas informações são armazenadas em disco (linhas 8-11). Esta operação é invocada pelo agente C2FS na operação flush garantindo assim que no fecho de qualquer ficheiro os dados serão actualizados na cloud-of-clouds. Esta operação pode também ser invocada pelo agente C2FS na operação fsync se o utilizador do C2FS assim o quiser. Note-se que desde que o ficheiro é aberto até ser fechado, pode ser requerida muitas vezes a sua sincronização (através de chamada ao sistema fsync). Assim, sincronizar os dados na cloud-of-clouds com a operação fsync, embora ofereça garantias mais seguras (por exemplo, tolerar a falha do disco), significa uma diminuição na performance do C2FS. Algorithm 6: Sync W Clouds Map h String, byte[] i hashs; Map h String, boolean i valueToSend; Map h String, int i sizes; CacheOnDiskManager cacheDisk; 1 2 3 4 5 6 7 8 9 10 Entrada: name - identificador do ficheiro, key - chave para encriptar os dados Saı́da: nenhuma inı́cio se (valueT oSend.get(name) = true) então Sync W Disk(name); data ←− cacheDisk.getData(name, 0, sizes.get(name)); cipherData ←− encryptData(key, data); newHash ←− Send By M odel(name, cipherData); notif yDirectoryService(name, newHash, data.length); hashs.add(name, newHash); valueT oSend.add(name, f alse); write to disk(name, newHash, f alse); fim Operação Delete Data. Esta operação serve para eliminar um ficheiro do disco local. Os ficheiros não são eliminados das clouds durante esta operação para evitar a diminuição do desempenho do sistema, uma vez que para um determinado ficheiro não ficar visı́vel aos clientes após a sua eliminação basta eliminar os metadados a ele referentes. Outro motivo para não se proceder à eliminação dos dados nas clouds nesta operação deve-se ao facto da necessidade de concretizar um colector de lixo que elimine as versões antigas Capı́tulo 3. Armazenamento de Dados do C2FS 42 de ficheiros ainda não eliminados. Assim, faz sentido proceder à eliminação de dados nas clouds, quer seja de versões antigas ou mesmo de todas as versões de um ficheiro (se já tiver sido eliminado), no mesmo protocolo (secção 3.4.5). Além de eliminar o ficheiro do disco, elimina também todas as entradas em todas as estruturas mantidas pelo serviço de armazenamento referentes a ele, incluindo a estrutura de resumos criptográficos, a estrutura que mantém os ficheiros que têm que ser enviados para as clouds, a estrutura que mantém o tamanho dos ficheiros e, se o modelo de envio de dados por assı́ncrono, da fila de envio (secção 3.4.3). Esta operação é integrada no agente C2FS na operação unlink. Operação Release Data. Esta operação tem o objectivo de libertar o ficheiro. Primeiro o ficheiro deve ser eliminado da memória volátil se esta o contiver. Depois, o lock efectuado sobre o ficheiro deve ser libertado através do serviço de locks [32]. No caso do modelo de envio ser sı́ncrono, o ficheiro é libertado no instante, pois este não está a ser enviado. Já no caso de o modelo ser assı́ncrono, se o ficheiro estiver a ser enviado ou ainda estiver na fila de envio, o ficheiro só é libertado quando o seu envio em background terminar. Esta operação é invocada pelo agente C2FS na operação release de forma a libertar o ficheiro após todos os descriptores associados a este serem fechados. Como já descrito anteriormente na tabela 3.1, sobre um ficheiro aberto podem existir vários descriptores se por exemplo a aplicação fizer uso da função fork, e sobre cada um destes descriptores, que apontam para o mesmo ficheiro, é invocada a operação flush. Já a operação release é invocada só quando o último descriptor for fechado. Ilustração do Funcionamento. A fig 3.4 mostra, de uma forma resumida, uma possı́vel sequência de chamadas ao sistema que uma qualquer aplicação pode exercer, e o que elas desencadeiam no agente C2FS e, por sua vez, no serviço de armazenamento aquando do uso da cache em memória. Note-se que nesta imagem está escondida a interacção existente com os serviços de directorias e locks [32]. A cache em memória permite assim melhorar o desempenho do C2FS (principalmente quando se opera em ficheiros grandes) aquando de sucessivas operações de escrita ou de leitura num mesmo conjunto de ficheiros. Isto porque quando um ficheiro é aberto (open), a operação Update Cache é chamada e o ficheiro é carregado para memória. Depois todas as escritas e/ou leituras que são efectuadas sobre um ficheiro aberto são efectuadas sobre a memória volátil. Quando o ficheiro é fechado, é chamada a operação Sync W Clouds que armazena devidamente as actualizações nas clouds e posteriormente a operação Release Data que liberta o ficheiro da memória. Capı́tulo 3. Armazenamento de Dados do C2FS 43 Figura 3.4: Desencadeamento das chamadas ao sistema no serviço de armazenamento. 3.4.3 Modelo de Envio de Dados Como já mencionado nas secções anteriores, o serviço de armazenamento pode ser configurado para efectuar escritas sı́ncronas ou assı́ncronas de ficheiros para a cloud-ofclouds, tendo esta escolha influência nas garantias de consistência dos dados em cache fornecidas pelo serviço. Nos pontos seguinte são descritos estes dois modelos. • No caso de as escritas serem sı́ncronas, o retorno da operação Sync W Clouds garante que os ficheiros já estão devidamente armazenados na cloud-of-clouds. Esta garantia deve-se ao facto do cliente ser obrigado a esperar a confirmação da escrita do ficheiro nas clouds, tendo a garantia que, após a conclusão da operação, o ficheiro está correctamente armazenado. Assim a utilização deste tipo de escritas fornece tolerância a faltas do disco local uma vez que o cliente tem a garantia que após o retorno da operação, o disco pode falhar pois os dados podem ser recuperados das clouds. • No caso de serem utilizadas escritas assı́ncronas, tal não se verifica, pois o cliente não tem garantias do momento em que o ficheiro irá chegar às clouds. Embora exista uma diminuição das garantias de consistência da cache, a utilização deste tipo de escritas representa um significativo aumento do desempenho do sistema. A concretização deste modelo de envio envolve um sistema de filas onde existe prioridade de envio para os primeiros ficheiros que forem adicionados a esta. O sistema 44 Capı́tulo 3. Armazenamento de Dados do C2FS mantém assim tarefas em background a enviar dados de ficheiros diferentes em simultâneo de modo a maximizar o desempenho. O número de tarefas a desempenhar este trabalho é configurado pelo cliente. Sempre que uma das tarefas terminar o envio de um ficheiro, é iniciado outro envio caso existam ficheiros na fila. Note-se que se não houvesse este sistema de filas e que se sempre que se quisesse enviar um ficheiro assincronamente para as clouds fosse iniciada uma tarefa em background, a máquina onde o C2FS estaria a correr ficaria sobrelotada caso estivessem a ser enviados centenas de ficheiros em simultâneo. Se for adicionado um ficheiro à fila e este já lá existir, os dados que estavam para enviar são substituı́dos pelos novos evitando assim o envio de uma versão que já não é a mais actual. Como já descrito na operação Delete Data se um determinado ficheiro for eliminado enquanto está na fila, é também eliminado da fila, evitando assim o seu envio. Tanto a substituição de dados na fila como a sua eliminação representam uma diminuição nos custo relacionados com a transferência de dados para as clouds. 3.4.4 Durabilidade dos Dados A tabela 3.2 apresenta os diferentes nı́veis em que os dados são mantidos pelo serviço de armazenamento. O primeiro nı́vel diz respeito aos dados em memória volátil. Como podemos ver, é o nı́vel em que se verifica o melhor desempenho de sistema, pois cada operação de escrita ou de leitura é efectuada com uma latência na ordem dos microssegundos. Contudo não fornece nenhuma garantia no que diz respeito à tolerância de faltas. No segundo nı́vel, que é quando os dados atingem memória estável no disco local, o serviço de armazenamento suporta a falha da estação de trabalho onde o C2FS está a correr, podendo recuperar os dados depois do sistema ser reiniciado. No último nı́vel os dados são mantidos na cloud-of-clouds permitindo assim a partilha de ficheiros entre diferentes clientes. Como podemos ver na tabela, a partir do momento em que os dados estão armazenados na cloud-of-clouds o sistema suporta tanto a falha do disco local, como a falha de f clouds num sistema em que são utilizadas n − f [19]. Este é também o nı́vel em que a latência para as operações de escrita e leitura apresenta valor mais elevados. Este modelo de durabilidade, ou seja, as diferentes localizações em que os dados se encontram aliado à integração das operação que gerem os dados nestas localizações no C2FS, permite a este garantir um nı́vel de consistência forte (consistência ao fechar [26]). Localização dos Dados memória não estável disco local cloud-of-clouds Latência microssegundos milissegundos segundos Tolerância a Faltas nenhuma crash falha do disco e do provedor Tabela 3.2: Durabilidade dos dados. Partilha não não sim Capı́tulo 3. Armazenamento de Dados do C2FS 3.4.5 45 Colector de Lixo Conforme já mencionado anteriormente, cada escrita no DepSky representa uma versão nova nas clouds. Assim uma preocupação que este serviço tem que ter é a de eliminar versões antigas de ficheiros que ainda não tenham sido eliminados. Juntamente com o procedimento de eliminar versões antigas de ficheiro, são também eliminados das clouds os ficheiros que já foram eliminados do sistema de ficheiros mas que ainda estão armazenados nas clouds (operação Delete Data). Para a eliminação de versões antigas, o cliente do serviço é responsável por fornecer o número de versões que devem ser mantidas nas clouds (na continuação da descrição deste protocolo, este número é representado por v). Em ambos os casos, o objectivo principal, além de o de deixar mais espaço disponı́vel, é o de não obrigar os utilizadores do C2FS a pagar demasiado por dados obsoletos que não sejam mais necessários. Em baixo é explicado como se procede à eliminação de versões e à eliminação de ficheiros por completo: • Para a eliminação de versões que não sejam mais necessárias, o serviço de armazenamento utiliza o protocolo para colectar lixo disponibilizado pelo DepSKy (garbageColector(unidade de dados, número de versões a manter)). Este protocolo elimina todas as versões excepto as que o cliente especificar que quer manter. Por exemplo, se uma determinada unidade de dados do DepSky (que referencia um ficheiro no C2FS) contiver dez versões (sendo a primeira a mais recente) e este protocolo for invocado fornecendo como argumento a unidade de dados e o número de versões a manter (por exemplo se v tomar valor três), serão eliminadas todas as versões desde a quarta até à décima. • Para a eliminação de ficheiros é utilizada a operação deleteContainer(unidade de dados) disponibilizada pelo DepSky, que dado uma unidade de dados do DepSky elimina toda a informação a ela referente. Isto significa que em cada cloud são eliminadas todas as versões referentes a este ficheiro. Assim, o serviço de armazenamento do C2FS implementa um colector de lixo que quando activado, é responsável por estas duas acções. A complexidade da formulação deste protocolo é escolher o momento óptimo para activá-lo, pois para escolher este momento terı́amos que saber exactamente a carga de trabalho que seria exercida sobre o sistema. É excluı́da a hipótese de se concretizar este protocolo como um serviço externo ao C2FS onde darı́amos a responsabilidade ao cliente de o executar quando o bem entendesse. Uma das formas mais lógicas para activar o colector de lixo seria a cada t unidades de tempo. Contudo, este modelo poderia levantar alguns problemas. Primeiro, se o valor t tomasse valores pequenos, o cliente poderia ser obrigado a ter custos adicionais Capı́tulo 3. Armazenamento de Dados do C2FS 46 desnecessários, uma vez que teriam que ser listadas3 frequentemente todas as versões de todos os ficheiros, que poderiam até não ter nada para eliminar (se tivessem menos versões que aquelas a manter). Por outro lado, se o valor t tomasse valores grandes e o sistema sofresse de uma carga de trabalho com muitas escritas, o cliente iria pagar demasiado por uma grande quantidade de dados. Para activar o colector de lixo de uma forma o mais perto do óptimo possı́vel, o serviço de armazenamento oferece uma solução que tem em conta a quantidade total de bytes e o número total de versões que existem para eliminar, conseguindo assim não ter a necessidade de estudar a carga de trabalho a cada instante. A atenção prestada à totalidade de bytes transferidos permite accionar o protocolo num perı́odo de tempo razoável na eventualidade do utilizador do C2FS manter ficheiros grandes no sistema. Contudo, assim o protocolo pode levar muito tempo a ser activado se o utilizador do C2FS mantiver muitas versões pequenas no sistema. De forma a evitar isso é também dada atenção ao número de versões que estão para eliminar nas clouds. Assim, o colector de lixo é activado quando se verificar algum dos seguintes acontecimentos: • Se o número total de bytes a eliminar transferidos para as clouds for superior a X. • Se o número total de versões a eliminar presentes nas clouds for superior a Y . Para X foi escolhido o valor de 1,5 GB (1610612736 bytes). Como mencionado anteriormente o tamanho máximo por ficheiro para garantir uma boa performance do C2FS é de 50 MB. Este valor de X permite assim, no pior caso (assumindo 50 MB por ficheiro), limpar as clouds quando existem aproximadamente 31 versões. Já para Y foi escolhido o valor de 1500 versões. Note-se que se o valor de X não for atingido, temos aproximadamente cerca de 1 MB por cada uma desta 400 versões. Estes valores foram pensados para que o protocolo não demore muito tempo aquando da sua execução para não penalizar o desempenho do sistema. Contudo, estes valores podem não ser óptimos. Para encontrarmos os valores óptimos para X e Y terı́amos que efectuar um estudo mais aprofundado. Note-se que estes valores podem ser facilmente reconfigurados pelo cliente. Computando X e Y. O serviço de armazenamento faz a contagem do número de versões e da quantidade de bytes transferidos para as clouds por cada ficheiro. A contagem das versões é feita da seguinte forma: enquanto um determinado ficheiro estiver no seu tempo de vida (ainda não foi eliminado) são contadas todas as vezes que este foi transferido para as clouds. Esta contagem é só iniciada após v transferência (uma vez que enquanto não for eliminado, queremos lá manter nunca menos que v versões); quando o ficheiro for eliminado, o número de transferências para este é incrementado em v (uma vez que 3 Note-se que para a listagem de versões nas clouds está associado um preço, dependendo este preço do provedor. Capı́tulo 3. Armazenamento de Dados do C2FS 47 na próxima execução do colector de lixo têm que ser eliminadas todas as versões deste). Assim, a cada instante, o número total de versões que existem para eliminar são a soma de todas estas contagens para todos os ficheiros mantidos em cache. Para a contagem do número de bytes, assim como na contagem de versões, são somados para cada ficheiro os bytes transferidos em cada transferência. No caso de ficheiros já eliminados são contados os bytes transferidos em todas as escritas efectuadas, já no caso de ficheiros ainda no activo são contados os bytes transferidos para todas as escritas efectuadas com a excepção das últimas v escritas, pois estas não necessitam ser eliminadas4 . Para possibilitar a soma correcta do número de todas as versões a eliminar e do número total de bytes transferidos a cada instante, mesmo após o sistema ser reiniciado, são mantidas em disco local as estruturas que armazenam os números de versões e o número de bytes transferidos para cada ficheiro. Estas estruturas são actualizadas durante a execução do protocolo (depois de um ficheiro ser limpo, são eliminadas as entradas a ele referentes), para permitir a sua recuperação depois de uma falha. Note-se que não conseguimos contabilizar a totalidade de número de versões e o número de bytes presentes nas clouds para ficheiros partilhados, uma vez que os outros clientes também podem efectuar escritas nestes ficheiros. Contudo, assume-se que mais tarde ou mais cedo algum dos clientes irá limpar o ficheiro, uma vez que cada instância do C2FS executa um protocolo colector de lixo. Este colector de dados não funciona correctamente, no que diz respeito a ficheiros que já foram eliminados do sistema mas que ainda não foram eliminados das clouds, se o utilizador do C2FS mudar de estação de trabalho, pois perde-se os dados armazenado no disco local que referenciam esses mesmos ficheiros. Contudo, esta falha poderia ser facilmente corrigida se as estruturas fossem mantidas nas clouds. Mas devido às muitas actualizações que estas estruturas sofrem, o custo para o utilizador do C2FS seria muito excessivo, pois todas as actualização referidas anteriormente feitas no disco teriam que ser feitas nas clouds. 3.5 Considerações Finais Neste capı́tulo foi primeiro apresentada a visão geral do C2FS, um sistema de ficheiros para cloud-of-clouds que ao mesmo tempo que fornece disponibilidade, integridade e confidencialidade dos dados armazenado, permite também a partilha de ficheiros. Posteriormente foi descrito o módulo FUSE, que permite a implementação e execução do C2FS a nı́vel do utilizador. Foram também introduzidas as alterações feitas a nı́vel do DepSky de forma a este responder melhor às necessidades do DepSky. Por fim foi apresentado o 4 No entanto são armazenados em disco o número de bytes referentes a escritas recentes para podermos adicionar ao total de bytes transferidos o terceiro valor mais antigo quando uma nova transferência é efectuada. Capı́tulo 3. Armazenamento de Dados do C2FS 48 serviço de armazenamento do C2FS. Nesta secção foram descritas as operações que permitem gerir os dados nas três diferentes localizações que estes se podem encontrar sendo elas a memória, o disco, e a cloud-of-clouds. Por último foi explicado o colector de lixo que permite a limpeza de dados obsoletos nas clouds. No próximo capı́tulo são apresentados os detalhes de concretização presentes no serviço de armazenamento Capı́tulo 4 Concretização do Serviço de Armazenamento Neste capı́tulo são apresentados os aspectos relevantes da concretização do serviço de armazenamento do C2FS. Primeiro é apresentado o modelo de classes, e posteriormente alguns diagramas de sequência que mostram a interacção entre estas classes aquando da invocação das diferentes operações disponibilizadas. Como já mencionado na secção 3.2, tanto o DepSky [19] como o DepSpace [20] são concretizados na linguagem Java. Razão essa que levou à utilização do módulo FUSE-J [8] para a implementação do sistema de ficheiros. O serviço de armazenamento, sendo o componente com a função de gerir os dados do sistema de ficheiros no DepSky, também é concretizado na linguagem Java, facilitando a sua integração. Em relação á cifra dos dados efectuada por este serviço, é utilizada a técnica AES através das classes do pacote javax.crypto da plataforma Java. Em relação ao resumo criptográfico computado a nı́vel do DepSky, este é computado através do algortimo SHA1 utilizando a classe fornecida pela API do Java java.security.MessageDigest. De seguida é primeiramente apresentado o modelo de classes do sistema e posteriormente os diagramas de sequência para as operação de obtenção dos dados das clouds, da escrita do dados na cache e da escrita dos dados nas clouds. 4.1 Diagrama de Classes A figura 4.1 apresenta o diagrama de classes do serviço de armazenamento concretizado. O C2FSAgent é a classe que implementa o agente C2FS, ou seja, é a classe que integra o serviço de armazenamento, assim como os restantes serviços [32], na interface de sistema de ficheiros (secção 3.2). Esta classe mantém uma instância do objecto StorageService, objecto este que implementa a interface IStorageService. Esta interface foi pensada para responder da melhor forma possı́vel aos objectivos do C2FS. O objecto StorageService permite ao agente C2FS gerir os dados nas três diferentes localizações: memória, disco e cloud-of-clouds. Quando iniciado, este recebe parâmetros 49 Capı́tulo 4. Concretização do Serviço de Armazenamento 50 de configuração, e consoante estes parâmetros, assim são as instâncias que este cria para gerir os dados. Por omissão, o objecto do tipo StorageService mantém uma instância do objecto cacheDiskManager. Este objecto é responsável por efectuar todos os acessos ao disco, e de aplicar politicas LRU para a substituição de objectos em cache quando necessário. Para aceder ao disco, é utilizada a classe RandomAccessFile que permite aceder ao ficheiro em offsets diferentes. Este objecto mantém uma instância do StorageService para no caso da necessidade de substituir ficheiros em cache, serem invocadas as operações syncWClouds, para armazenar o ficheiro nas clouds caso seja necessário, e deleteData(containerId), para se proceder à limpeza de todas as entradas em todas as estruturas referentes ao ficheiro em cache a substituir . Contudo, consoante a configuração indicada pelo C2FSAgent, também este pode manter uma instância do objecto CacheMemoryManager. Assim como a classe descrita em cima, este objecto permite aceder a todos os ficheiros mantidos em memória através das operações genéricas de acesso à cache (ICacheManager). Este mantém uma instância do objecto CacheDiskManager de forma a garantir que um determinado ficheiro é devidamente armazenado em memória estável aquando da aplicação de politicas LRU. O objecto StorageService mantém também uma instância da classe DepSkyAcessor. Esta é a classe que opera directamente com o DepSky, e é também responsável por cifrar o ficheiro antes da sua escrita nas clouds, bem como por decifrar aquando da sua leitura. Se o C2FSAgent configurar o sistema para escrever assincronamente para as clouds, o objecto StorageService mantém também um objecto do tipo SendingQueue. Esta classe permite a adição e remoção de ficheiros na fila de envio. O objecto que é mantido na fila é o ObjectInQueue que armazena a informação necessária para o envio. O envio neste caso é feito através do objecto DataSync que representa uma thread possibilitando assim o envio dos dados em background. Neste caso, cada thread de envio mantém uma instância diferente do DepSkyAcessor para o envio de diferentes ficheiros ser feito em paralelo. A classe DataStatsManager mantem uma Map de objectos do tipo DataStats. Cada objecto destes guarda as informações que são necessárias manter em disco sobre cada ficheiro em cache. A classe é assim responsável por efectuar todas as actualizações nos objectos DataStats e armazenar estas actualizações em disco. Esta classe tem também um objecto do tipo GarbageCollectorService onde são armazenadas as informações necessárias para a activação do colector de lixo (Garbagecollector). A tabela 4.1 mostra as linhas de código para cada componente do sistema. 4.2 Diagramas de Sequência Nesta secção são apresentados três diagramas de sequência diferentes presentes nas figuras 4.2, 4.3 e 4.4. O primeiro representa o fluxo de operações existente no serviço Capı́tulo 4. Concretização do Serviço de Armazenamento Figura 4.1: Modelo de classes do sistema. 51 Capı́tulo 4. Concretização do Serviço de Armazenamento Classe C2FSAgent StorageService DiskCacheManager MemoryCacheManager DepSkyAcessor DataStats DataStatsManager SendingQueue DataSync GarbageCollector GarbageCollectorService 52 Número de Linhas de Código 988 322 85 70 75 40 250 85 80 150 40 Tabela 4.1: Linhas de código das classes do serviço de armazenamento de armazenamento aquando da operação de actualização da cache. O segundo diagrama é referente à operação de escrita na cache. Por fim, o terceiro, representa a operação de sincronização dos dados na cloud-of-clouds. No primeiro e no último diagrama é escondido o retorno da operação (erro ou ok) de forma a simplificá-los. Leitura das clouds. A figura 4.2 mostra o fluxo presente na operação de actualização da cache. Em primeiro lugar é obtido o objecto representante do fileId fornecido. No caso de o ficheiro não existir em cache, é criado um novo objecto DataStats para este novo ficheiro e este é adicionado à Map que guarda os objectos deste tipo. Após obtido o hash referente à versão em cache (através do objecto DataStats), é necessário verificar se este é igual ao hash fornecido pelo agente C2FS, pois se for igual significa que os dados em cache são os mesmos que os dados presentes nas clouds, não sendo assim necessário efectuar o download. Como podemos ver no diagrama, caso o download seja necessário, o objecto StorageService tenta obter no máximo 4 vezes o ficheiro das clouds através do objecto DepSkyAcessor. Este objecto, por sua vez lê os dados usando o DepSky DepSky através da operação readMatching(Du, hash) e, caso consiga obter os dados correspondentes ao hash fornecido, decifra-os e retorna os dados em claro, caso contrário retorna null. No caso de não se conseguir obter os dados em nenhuma das quatro tentativas é retornado erro ao C2FSAgent. Se os dados conseguirem ser obtidos, são então colocado na cache em disco através do objecto DiskCacheManager. Depois o objecto presente na Map de objectos do tipo DataStats referente a este ficheiro é actualizado com o novo estado (actualizado), com o novo tamanho e com o novo resumo criptográfico (referente aos dados lidos). Note-se que o objecto é escrito para disco pelo objecto DataStatsManager só quando o hash é actualizado. Capı́tulo 4. Concretização do Serviço de Armazenamento 53 Esta operação escreve ainda os dados em memória através do objecto MemoryCacheManager, quer tenha sido necessário efectuar a leitura das clouds ou não. Escrita na cache. O diagrama presente na figura 4.3 mostra o fluxo de mensagens efectuado na operação de escrita em cache. Quando o objecto StorageService recebe uma operação de escrita em cache, este encaminha o pedido de escrita para o local pretendido. Ou seja, para o objecto MemorycacheManager caso o StorageService esteja configurado para a utilização de cache em memória, ou para o disco caso contrário. Note-se que antes de efectuar a escrita, o estado do objecto é alterado para true, definindo assim que este ficheiro sofreu alterações e necessita ser armazenado em memória estável. No caso de a escrita ser efectuada para o objecto DiskcacheManager, esta alteração é também armazenada em disco através do objecto DataStatsManager explicitando-o no terceiro argumento da operação setState, de forma a possibilitar a recuperação na ocorrência de uma falha antes do seu envio para as clouds. Por fim, é verificado se a escrita alterou o tamanho do ficheiro. Caso tenha alterado, o novo tamanho é armazenado no objecto DataStats referente ao ficheiro escrito e este novo tamanho é retornado ao agente C2FS. Caso contrário, retorna o tamanho que já existente no objecto DataStats. Escrita nas clouds. A figura 4.4 apresenta o diagrama de sequência da operação que escreve os dados presentes em cache na cloud-of-clouds. A primeira preocupação da operação é a de chamar a operação syncDisk(containerId) de modo que os dados actualizados em memória fiquem armazenados em disco de forma a garantir a coerência da cache em memória estável com os dados presentes nas clouds. O próximo passo é obter o estado do ficheiro através do objecto DataStatsManager que gere a Map de objectos do tipo DataStats. Se o estado estiver a false significa que não houve alterações no ficheiro (provavelmente ocorreram só operações de leitura) e portanto não é necessário enviá-lo para as clouds. Caso contrário, este tem que ser enviado. Neste caso os dados são então obtidos da cache através do objecto DiskCacheManager. Se o C2FSAgent utilizar escritas assı́ncronas, os dados são adicionados ao objecto SendingQueue que gere a fila de envio. O fluxo da operação presente aquando da adição de um novo objecto na fila não está presente de forma a simplificar o diagrama. Já se o envio for sı́ncrono, o StorageService chama a operação de escrita para o DepSky presente no objecto DepSkyAcessor. Este, antes de escrever no DepSky, cifra os dados com a chave fornecida. Após a escrita, o objecto DataStats referente ao ficheiro enviado é actualizado com o estado a false, de forma a não serem enviados os mesmos dados para as clouds, e o hash que resulta da escrita no DepSky substitui o hash antigo. Aquando da actualização do hash, o objecto DataStats é armazenado em disco. De seguida o objecto DataStatsManager é também notificado com o número de bytes transferidos para a cloud. Este por sua vez actualiza esta informação no objecto GarbageCollectorService Capı́tulo 4. Concretização do Serviço de Armazenamento Figura 4.2: Operação de leitura das clouds. 54 Capı́tulo 4. Concretização do Serviço de Armazenamento 55 Figura 4.3: Operação de escrita em cache. para permitir a activação do colector de lixo. Por fim o DirectoryService é notificado com o novo hash e como o tamanho dos dados escritos e posteriormente é chamada a operação commitLocalMetadata para proceder ao envio dos metadados para os servidores. 4.3 Agente C2FS Como já mencionado várias vezes anteriormente, o agente C2FS é o componente que implementa as operações do sistema de ficheiros e que integra os três diferentes serviços (armazenamento, directorias e locks) onde, consoante a semântica de cada operação, assim as operações dos diferentes serviços a invocar. Assim como o serviço de armazenamento, este por sua vez também é configurável. Em baixo são listadas os parâmetros de configuração que os clientes podem utilizar aquando da montagem do sistema de ficheiros no Linux: • -use memory cache - indica que o sistema irá usar o serviço de armazenamento com cache em memória volátil (por omissão só é utilizada cache em disco); • -assync model - indica que o sistema irá usar o serviço de armazenamento com escritas assı́ncronas (por omissão utiliza escritas sı́ncronas); • -max memory size=size - indica o tamanho máximo da cache em memória no serviço de armazenamento (por omissão size = 1 GB); Capı́tulo 4. Concretização do Serviço de Armazenamento Figura 4.4: Operação de escrita para as clouds. 56 Capı́tulo 4. Concretização do Serviço de Armazenamento 57 • -num threads=num - indica o número de threads a enviar dados em background (por omissão num = 4); • -mantain old version=num - indica o número de versões a manter para cada ficheiro aquando da execução do colector de lixo (por omissão num = 3). • -fsync to clouds - indica que a operação fsync envias os dados para as clouds (por omissão escreve-os na cache em disco); • -use non sharing DS - indica que o sistema irá usar o serviço de directorias sem partilha de ficheiros (por omissão utiliza a partilha de ficheiros); • -delta=time - indica o tempo de validade dos metadados em cache (por omissão time = 0). 4.4 Considerações Finais Neste capı́tulo foram apresentado alguns detalhes de implementação do serviço de armazenamento. Primeiro foi descrito o modelo de classes e como os diferentes componentes interagem entre si. Posteriormente foram ilustrados os modelos de sequência para as operações de actualização da cache através da leitura dos dados das clouds, de escrita na cache (tanto em memória como em disco) e de escrita dos dados actualizados na cloud-of-clouds. No próximo capı́tulo é apresentada uma avaliação experimental do desempenho deste serviço e do C2FS. Capı́tulo 4. Concretização do Serviço de Armazenamento 58 Capı́tulo 5 Avaliação Neste capı́tulo é apresentada uma avaliação do serviço de armazenamento para o C2FS. Em primeiro lugar serão apresentadas as latências inerentes ao envio de dados para as clouds para diferentes tamanhos de ficheiros. De seguida serão mostradas medições de desempenho efectuadas ao C2FS com diferentes configurações. Por fim, será comparado o desempenho do C2FS ao desempenho de outros dois sistemas de ficheiros para clouds, nomeadamente o S3FS [16] e o S3QL [17]. 5.1 Metodologia As medições apresentadas neste capı́tulo foram obtidas executando três diferentes benchmarks, sendo eles o Iozone [10], o PostMark [27] e o Filebench [6]. O Iozone exercita operações de escrita e leitura sequenciais e aleatórias sobre um ficheiro. O PostMark, embora apresente um comportamento mais adequado para testar a gestão de metadados (criação e destruição de ficheiros pequenos), pode ser configurado para criar ficheiros com um tamanho considerável, podendo assim testar o comportamento do serviço de armazenamento aquando de operações de escritas e leituras em diferentes ficheiros ao mesmo tempo. Por fim, o Filebench permite testar diferentes tipos de workloads. Neste caso foi utilizado o workload randomrw que permite exercitar operações de escrita e leitura aleatórias sobre o mesmo ficheiro. Os diferentes benchmarks foram configurados da seguinte forma: • Iozone - Este foi configurado para testar operações de escrita e leitura sequenciais e não sequenciais para ficheiros com 512 KB, 1, 2, 4, 8, 16 e 32 Mb. • PostMark - Este, por sua vez, foi configurado para criar e operar sobre 764 ficheiro com tamanhos aleatórios entre 512 Kb e 2 Mb. • Worload randomrw - Por fim, este foi configurado para exercer carga de trabalho no C2FS através de 6 threads diferentes (3 para leituras e 3 para escritas) num único ficheiro de 50MB. 59 Capı́tulo 5. Avaliação 60 Nestes três benchmarks podemos avaliar o comportamento do serviço de armazenamento para algumas das propriedades descritas no trabalho apresentado em [25] para os workloads das aplicações de hoje em dia, nomeadamente o acesso a muitos ficheiros em simultâneo, escritas e leituras aleatórias e acessos efectuados a partir de diferentes threads. Todas as medições foram efectuadas num computador com aproximadamente 2 anos, localizado em Lisboa. Este computador tem como caracterı́sticas principais um processador 2.4 GHz Intel Core 2 Duo, e uma memória de 4GB DDR3. Para efectuar as medições foi utilizado um serviço de internet com ligação de 23.67 Mbps de download e 5.06 Mbps de upload. O DepSky [19] foi configurado para replicar os dados por 4 diferentes provedores de armazenamento, sendo eles Amazon S3 [4], RackSpace [15], Windows Azure [11] e Google Storage [9]. O driver de acesso esta última cloud foi desenvolvido de raiz para estes experimentos já que o DepSky original não suportava este serviço [19]. É importante referir ainda que os servidores utilizados para a Amazon S3, RackSpace e Windows Azure estão localizados na Europa, enquanto que o servidor utilizado para armazenar os dados na Google Storage situa-se no Estados Unidos. O serviço de directorias utilizado para esta avaliação foi uma versão sem partilha de ficheiros, na qual os metadados não são armazenado no DepSpace [32]. Esta escolha justifica-se com o objectivo de minimizar a influência deste serviço nos resultados obtidos. 5.2 Latência das Escritas e Leituras de Dados Na figura 5.1 são apresentadas as latências experienciadas aquando da escrita e da leitura de dados para as clouds através do DepSky. Estes valores foram obtidos através da execução do benchmark Iozone. Foram medidas as latências para escritas e leituras de dados com seis distintos tamanhos, sendo eles 512KB, 1, 2, 4, 8, 16 e 32MB. Para cada um dos tamanhos dos blocos de dados testados foram executas 100 operações. Como podemos observar no gráfico 5.1(a), as latências obtidas para as escritas sofrem uma perda de desempenho mais ou menos proporcional ao tamanho dos dados escritos. Este aumento proporcional da latência deve-se ao facto de alguns dos provedores de armazenamento utilizados sofrerem desta propriedade, como é descrito em [37]. No gráfico 5.1(b) podemos observar que as latências obtidas para as leituras apresentam um comportamento semelhante ao anterior, com a excepção de que os valores medidos para os mesmos tamanhos dos dados são muito mais baixos. Os tempos de latência apresentados na figura são superiores aos tempos apresentados no projecto atrás referido. Isto deve-se ao facto de os testes apresentados em [37] terem sido efectuados na rede do Departamento de Informática, sendo o desempenho desta rede muito superior ao da ligações da internet utilizada. 61 Capı́tulo 5. Avaliação (a) Escritas. (b) Leituras. Figura 5.1: Latência das escritas e leituras (em segundos) para a cloud-of-clouds 5.3 Desempenho do Serviço de Armazenamento do C2FS Nesta secção serão medidos os tempos de execução dos benchmarks IOzone e Postmark para as diferentes configurações do serviço de armazenamento do C2FS. Pretende-se então perceber de que forma é que estas configurações afectam o desempenho do sistema. Todos os resultados apresentados nesta secção resultam de uma média de 5 execuções de cada experimento. Escritas sı́ncronas. A figura 5.2 mostra o desempenho do serviço de armazenamento quando configurado para efectuar escritas sı́ncronas para as clouds. É comparado o desempenho do sistema quando este utiliza cache em disco ou memória volátil, e ainda com as duas diferentes configurações da operação fsync (só para disco, ou para cloud-of-clouds assegurando também que os dados ficam armazenados em disco). Umas das conclusões a retirar deste gráfico é que, como seria expectável, existe um ganho muito grande aquando da utilização da cache em memória para efectuar as operações de escrita e leitura. Como podemos verificar, no caso do IOzone o tempo médio de execução diminui para cerca de metade. Já no caso do tempo de execução do PostMark, este diminui para cerca de um terço aquando da utilização de memória para efectuar operações de E/S. Como também se pode verificar, as diferentes configurações da operação fsync resultam em alterações marginais no desempenho do sistema para os dois benchmarks utilizados. Isto justifica-se com o facto do IOzone só efectuar a operação referida acima no momento exacto antes do fecho do ficheiro. Note-se que antes de qualquer envio de dados para as clouds, estes são devidamente armazenados em disco. Assim, visto os dados serem enviados na operação fsync, não existem alterações em cache que obrigue o envio dos dados no fecho do ficheiro. No caso do PostMark não é efectuada nenhum fsync. Capı́tulo 5. Avaliação 62 Figura 5.2: Tempo de execução (em segundos) do IOzone e PostMark para escritas sı́ncronas. Escritas assı́ncronas. A figura 5.3 mostra o desempenho do C2FS quando utiliza escritas assı́ncronas para as clouds. Assim como na avaliação efectuada acima, é também avaliado neste caso o desempenho do sistema quando utiliza a cache em disco e em memória, assim como com as duas configurações da operação fsync. Figura 5.3: Tempo de execução (em segundos) do IOzone e PostMark para escritas assı́ncronas. Tal como anteriormente referido, também aqui podemos verificar o grande aumento 63 Capı́tulo 5. Avaliação de desempenho quando o serviço de armazenamento utiliza a cache em memória. Nesta caso em concreto, podemos verificar a especial utilidade deste nı́vel de cache quando se opera sobre ficheiros relativamente grandes. Esta conclusão pode retirar-se da figura, na qual existe um ganho muito significante no caso do IOzone (que opera sobre ficheiros até 32MB), ao contrário do observado no PostMark, que devido à utilização de ficheiros de (no máximo) 2MB, tem um ganho de desempenho mais modesto. Pelas mesmas razões apontadas anteriormente, a alteração da forma de funcionamento da operação fsync não representa alterações relevantes nos tempos de execução dos benchmarks. 5.4 Comparação do C2FS com outros Sistemas de Ficheiros para Cloud Nesta secção será comparado o desempenho do C2FS com o S3FS e com o S3QL. Nos vários experimentos apresentados nesta secção, tanto o S3FS como o S3QL foram configurados para armazenarem os seus dados na zona de disponibilidade da “Europa” do Amazon S3 [4]. Débito e Latência das Operações. A figura 5.4 apresenta a latência e débito das operações de escrita e leitura dos vários sistemas. Os valores apresentados foram obtidos através da execução do workload randomrw do Filebench, resultando estes da média de 5 execuções distintas deste experimento. Visto o workload só ter em conta as operações de escrita e leitura, a única configuração do serviço de armazenamento relevantes para este experimento é o nı́vel de cache a utilizar. (a) Latência. (b) Débito. Figura 5.4: Latência e throughput das operações de escrita e leitura não sequenciais. Valores medidos através da execução do workload randomrw do Filebench 64 Capı́tulo 5. Avaliação Como podemos constatar na figura 5.4(a), o único experimento que apresenta uma latência superior a 1 ms por operação de leitura é o C2FS quando opera sobre os dados em disco. No entanto, nas escritas, podemos verificar que esta configuração do C2FS apresenta melhor desempenho que o S3FS. Podemos ainda observar que o experimento com melhor desempenho para as escritas é o C2FS quando utiliza a cache em memória principal. Assim, na figura 5.4(b) é fácil perceber que o C2FS com leituras feitas na cache em disco apresenta novamente os piores resultados, tendo no entando um desempenho comparável ao S3FS no que diz respeito às operações de escrita. Podemos ainda verificar que o C2FS quando configurado para operar sobre os dados em memória apresenta pior débito de leituras, apresentando no entanto o melhor débito de escritas de todos os sistemas avaliados. A única explicação encontrada para o C2FS ter um menor débito de leituras que o S3FS e que o S3QL está relacionada com o uso do FUSE-J, uma vez que na prática, uma leitura no serviço de armazenamento do C2FS requer apenas cópias de bytes de memória principal para memória principal. Tempos de Execução. Nas tabelas abaixo são comparados os tempos de execução do IOzone e do PostMark obtidos pelo S3FS, S3QL e C2FS. Na tabela 5.1 é comparado o desempenho do C2FS quando configurado para efectuar escritas bloqueantes, e quando opera tanto na cache em disco como na cache em memória. Esta comparação faz sentido pois o S3FS efectua todas as escritas para a Amazon S3 sincronamente aquando do fecho do ficheiro. IOzone PostMark S3FS 2520.67 7737.5 Block + Disk + SyncD 3770.6 8632.25 Block + Memory + SyncD 1836.5 2725.5 Tabela 5.1: Comparação dos tempos de execução (em segundos) com o S3FS. Como podemos verificar na tabela 5.1, o desempenho do C2FS com cache em disco é inferior ao desempenho do S3FS em ambos os benchmarks. Contudo, quando é utilizada a cache em memória para efectuar as operações de escrita e leitura, o C2FS apresenta um desempenho muito mais satisfatório que o S3FS, ao mesmo tempo que fornece mais garantias no que diz respeito à disponibilidade dos dados, pois estes, ao contrário do S3FS, são armazenados na cloud-of-clouds. Por sua vez, na tabela 5.2 são comparados os tempos de execução, para os mesmo benchmarks, do S3QL e do C2FS quando efectua escritas assı́ncronas para as clouds. Esta comparação é efectuada pois o S3QL envia também todos os dados para a cloud assincronamente. 65 Capı́tulo 5. Avaliação IOzone PostMark S3QL 19.59 3024.5 NonBlock + Disk + SyncD 2391.74 208.8 NonBlock + Memory + SyncD 30.27 153.25 Tabela 5.2: Comparação dos tempos de execução (em segundos) com o S3QL. No caso da tabela 5.2 podemos verificar que quando testados o S3QL e o C2FS com o IOzone, o S3QL apresenta o melhor resultado. Contudo, embora no caso do C2FS utilizar cache em disco obter resultado bastante inferiores ao S3QL, quando configurado para operar com cache em memória, este obtém um resultado comparável. Surpreendentemente, no que diz respeito aos tempos de execução obtidos através do PostMark, o S3QL apresenta um resultado bastante negativo quando comparado quer com o C2FS com cache em disco, como com cache em memória. Isto pode dever-se ao facto do S3QL ser lento a lidar com o metadados. 5.5 Considerações Finais Neste capı́tulo foi apresentada uma avaliação experimental do desempenho do serviço de armazenamento do C2FS. Primeiramente foram mostradas as latências observadas no envio de dados para as clouds aquando da execução dos testes ao sistema. Foi mostrado também que com a diminuição do nı́vel de tolerância a faltas e consistência, o desempenho aumenta drasticamente. Por fim foi mostrado que o C2FS, mesmo armazenando os dados na cloud-of-clouds, consegue em alguns casos obter desempenhos superiores aos sistemas de ficheiros para clouds comparados na execução de alguns benchmarks populares. No próximo capı́tulo, para finalizar este relatório, serão apresentadas a conclusão e o trabalho futuro a realizar. Capı́tulo 5. Avaliação 66 Capı́tulo 6 Conclusão Com o crescimento do armazenamento de dados em clouds, veio a necessidade de estudar técnicas que possam melhorar tanto a fiabilidade dos dados armazenados, como da forma de os armazenar. A fiabilidade dos dados torna-se um ponto essencial no armazenamento em clouds no sentido em que estes têm o total controlo sobre os mesmos. A forma disponibilizada para armazenar os dados também se revela um ponto importante pois tanto os utilizadores comuns como os programadores precisam de um acesso fácil a estes provedores de armazenamento. O C2FS, um sistema de ficheiros seguro e fiável para cloud-of-clouds, vem responder a estas necessidades, pois ao mesmo tempo que mantém os dados disponı́veis e confidencias, disponibiliza uma interface do estilo POSIX facilitando assim o acesso a estes. Neste trabalho foi apresentado o serviço de armazenamento desenvolvido para o C2FS, que armazena os dados na cloud-of-clouds recorrendo ao DepSky [19], tirando assim partido das propriedades que este oferece, sendo elas disponibilidade, integridade e confidencialidade dos dados. Este serviço mostra-se configurável, pois são disponibilizados dois nı́veis distintos de cache e dois modelos de envio de dados para as clouds. Isto é muito benéfico pois os clientes podem tirar partido do sistema consoante as suas necessidades. Na avaliação experimental efectuada mostrou-se que o desempenho do C2FS comparável aos sistemas de ficheiros para clouds testados ao mesmo tempo que fornece garantias mais fortes de fiabilidade. Mostrou-se também que, como seria expectável, à medida que relaxamos o nı́vel de coerência da cache e a tolerância a faltas, o desempenho aumenta de uma forma muito satisfatória. 6.1 Trabalho Futuro Para além do trabalho apresentado neste documento, existem ainda algumas tarefas em aberto que podem melhorar o C2FS como um todo. Um dos trabalhos futuros passa por estudar se, ao invés de armazenar em cache os dados de um ficheiro num único bloco, armazená-lo dividindo-o em blocos mais pequenos, irá aumentar o desempenho do C2FS. 67 Capı́tulo 6. Conclusão 68 Uma outra tarefa a executar no futuro consiste em alterar o DepSky. O C2FS, embora permita a partilha de ficheiros [32], só o permite se os diferentes utilizadores partilharem a mesma conta. Para tal não ser necessário, é preciso evoluir o DepSky de forma a este fornecer listas de controlo de acesso aos contentores de dados armazenados nas clouds. Uma outra optimização futura é estudar uma técnica que permita esconder a latência inerente ao envio de muitos ficheiros pequenos em separado. O que se pretende neste ponto é descobrir quais as melhores formas de agrupar ficheiros pequenos num único bloco de dados para enviar para as clouds. Por fim, é necessário também avaliar o comportamento e desempenho do sistema com workloads de aplicações desktop da actualidade [25]. Bibliografia [1] Amazon elastic block store. http://aws.amazon.com/ebs/. [2] Amazon elastic compute cloud. http://aws.amazon.com/ec2/. [3] Amazon elasticache. http://aws.amazon.com/elasticache/. [4] Amazon simple storage service. http://aws.amazon.com/s3/. [5] Apple icloud. http://www.apple.com/icloud/. [6] Filebench. http://sourceforge.net/apps/mediawiki/filebench. [7] Fuse. http://fuse.sourceforge.net/. [8] Fuse-j. http://fuse-j.sourceforge.net/. [9] Google cloud storage. https://developers.google.com/storage/. [10] IOzone Filesystem Benchmark. http://www.iozone.org/. [11] Microsoft Windows Azure. http://www.windowsazure.com/. [12] Openstack storage. http://www.openstack.org/software/openstack-storage/. [13] Posix. http://en.wikipedia.org/wiki/POSIX. [14] Project TCLOUDS - trustworthy clouds - privacy and resilience for internet-scale critical infrastructure. http://www.tclouds-project.eu/. [15] Rackspace Cloud Hosting. http://www.rackspace.co.uk/. [16] S3fs - fuse-based file system backed by amazon s3. http://code.google.com/p/s3fs/. [17] S3ql - a full-featured http://code.google.com/p/s3ql/. file system 69 for online data storage. Bibliografia 70 [18] M. Abd-El-Malek, W. Courtright II, C. Cranor, G. Ganger, J. Hendricks, A. Klosterman, M. Mesnier, Prasad M, B. Salmon, R. Sambasivan, S. Sinnamohideen, J. Strunk, Eno Thereska, M. Wachs, and J. Wylie. Ursa minor: versatile clusterbased sotrage. In Proceedings of the 4th USENIX Conf. on File and Storage Techonogy (FAST’05), December 2005. [19] Alysson Bessani, Miguel Correia, Bruno Quaresma, Fernando Andre, and Paulo Sousa. DepSky: Dependable and Secure Storage in cloud-of-clouds. In Proc. of the 3rd ACM European Systems Conference – EuroSys’11, April 2011. [20] Alysson N. Bessani, Eduardo P. Alchieri, Miguel Correia, and Joni S. Fraga. DepSpace: a Byzantine fault-tolerant coordination service. In Proc. of the 3rd ACM European Systems Conference – EuroSys’08, pages 163–176, April 2008. [21] Miguel Castro and Barbara Liskov. Practical Byzantine fault-tolerance and proactive recovery. ACM Transactions Computer Systems, 20(4):398–461, November 2002. [22] George Coulouris, Jean Dollimore, and Tim Kindberg. Distributed Systems - Concepts and Designs, chapter Distributed File Systems, pages 323–364. 2005. [23] Abu-Libdeh et al. RACS. Redundant array of cloud storage. In ACM SOCC 2010. [24] Garth Gibson, David Nagle, Khalil Amiri, Jeff Butler, Fay Chang, Howard Gobioff, Charles Hardin, Erik Riedel, David Rochberg, and Jim Zelenka. A cost-effective, high-bandwidth storage architecture. In Proc. of the 8th Int. Conference on Architectural Support for Programming Languages and Operating Systems - ASPLOS’98, pages 92–103, 1998. [25] Tyler Harter, Chris Dragga, Michael Vaughn, Andrea C. Arpaci-Dusseau, and Remzi H. Arpaci-Dusseau. A File is Not a File: Understanding the I/O Behavior of apple desktop applications. In Proceedings of the 23rd ACM Symposium on Operating Systems Principles – SOSP’11, October 2011. [26] J. H. Howard, M. L. Kazar, Menees S. G., D. N. Nichols, M. Satyanarayanan, R. N. Sidebotham, and M. J. West. Scale and performance in a distributed file system. In ACM Trans. Comput. Syst. vol. 6, no. I, February 1988. [27] Jeffrey Katcher. PostMark: A New File System Benchmark. Technical report, August 1997. [28] J. Kubiatowicz, D. Bindel, Yan Chen, S. Czerwinski, P. Eaton, D. Geels, R. Gummadi, S. Rhea, H. Weatherspoon, W. Weimer, C. Wells, and Ben Zhao. Oceanstore: An architecture for global-scale persistent storage. In Proceedings of the 9th Intl. Bibliografia 71 Conf. on Architectural Support for Programming Langauges and Operating Systems, November 2000. [29] Edward L. Lee and Chandramohan A. Thekkath. Petal: Distributed virtual disks. In Proceedings of the 7th Intl. Conf. on Architectural Support for Programming Langauges and Operating Systems. pages 84-92, October 1996. [30] Barbara Liskov. From viewstamped replication to byzantine fault tolerance. In Replication, LNCS 5959, pages 121-149, 2010. [31] N. Megiddo and D. Modha. Arc: A self tuning, low overhead replacement cache. In Proceedings of USENIX Conference on (FAST) File and Storage Technologies, 2003. [32] R. Mendes. Substrato de coordenação para sistemas de ficheiros para cloud-ofclouds. Relatório do Projecto de Engenharia Informática. DI/FCUL, September 2012. [33] Ricardo Mendes, Tiago Oliveira, Alysson Bessani, and Marcelo Pasin. C2FS: um Sistema de Ficheiros Seguro e Fiável para Cloud-of-clouds. In INForum12, September 2012. [34] David A. Patterson, Garth Gibson, and Randy H. Katz. A case for redundant arrays of inexpensive disks (raid). In Proc. of the 1988 ACM SIGMOD International Conference on Management of Data, pages 109–116, 1988. [35] C. Plaxton, R. Rajaraman, and A. Aggarwal. Accessing nearby copies of replicated objects in a distributed environment. In Proceedings of ACM SPAA, pages 311-320, Newport, Rhode Island, June 1999. [36] Krishna P. N. Puttaswamy, Thyaga Nandagopal, and Murali Kodialam. Frugal Storage for Cloud File Systems. In Proc. of the 3rd ACM European Systems Conference – EuroSys’12, April 2012. [37] B. Quaresma. Depsky: Sistema de Armazenamento em Clouds Tolerante a Intrusões. Relatório do Projecto de Engenharia Informática. DI/FCUL, Setembro 2010. [38] R. L. Rivest. International conference on distributed computing systems. In IEEE Computer Society Press, 1989. [39] R. L. Rivest. The md5 message-digest algorithm, rfc-1321. In Network Working Group, IETF, April 1992. Bibliografia 72 [40] M. Satyanarayanan, J. H. Howard, D. N. Nichols, R. N. Sidebotham, A. Z. Spector, and M. J. West. The ITC distributed file system: principles and design. In Proceedings of the 10th ACM Symposium Oper. Syst. Principles. Orcas Island, December 1985. [41] M. Satyanarayanan, P. Kumar, M. Okasaki, E. Siegel, and D. Steere. Coda: A highly available file system for a distributed workstation environment. In IEEE Trans. on Comp. 4. 39 (Apr 1990), 447-459. [42] J. Sousa and A. Bessani. From byzantine consensus to bft state machine replication: A latency-optimal transformation. In In the Proc. of the 9th European Dependable Computing Conference, 2012. [43] C. Thekkath and E. L. T. Mann. Frangipani: A scalable distributed file system. In In the Proceedings of the 16th SOSP. [44] Michael Vrable, Stefan Savage, and Geoffrey M. Voelker. Cumulus: Filesystem backup to the cloud. volume 5, pages 1–28, 2009. [45] Michael Vrable, Stefan Savage, and Geoffrey M. Voelker. BlueSky: A cloud-backed file system for the enterprise. In Proc. of the 10th USENIX Conference on File and Storage Technologies – FAST’12, 2012. [46] S. A. Weil, S. A. Brandt, E. L. Miller, and C. Maltzahn. CRUSH: Controlled, scalable, decentralized placement of replicated data. In Proceedings of the 2006 ACM/IEEE Conference on Supercomputing (SC ’06). Tampa, FL, Nov, 2006, ACM. [47] Sage A. Weil, Scott A. Brandt, Ethan L. Miller, Darrell D. E. Long, and Carlos Maltzahn. Ceph: A scalable, high-performance distributed file system. In Proc. of the 7th USENIX Symposium on Operating Systems Design and Implementation – OSDI 2006, pages 307–320, 2006.