[haiku-commits] r40335 - haiku/trunk/src/add-ons/kernel/file_systems/btrfs

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 31 Jan 2011 20:16:14 +0100 (CET)

Author: korli
Date: 2011-01-31 20:16:14 +0100 (Mon, 31 Jan 2011)
New Revision: 40335
Changeset: http://dev.haiku-os.org/changeset/40335

Added:
   haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.h
   haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.h
Modified:
   haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Jamfile
   haiku/trunk/src/add-ons/kernel/file_systems/btrfs/btrfs.h
   haiku/trunk/src/add-ons/kernel/file_systems/btrfs/kernel_interface.cpp
Log:
added read only attribute support for btrfs.


Added: haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.cpp             
                (rev 0)
+++ haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.cpp     
2011-01-31 19:16:14 UTC (rev 40335)
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2010-2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
+ * Copyright 2010, François Revol, <revol@xxxxxxx>.
+ * Copyright 2004-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * This file may be used under the terms of the MIT License.
+ */
+
+//!    connection between pure inode and kernel_interface attributes
+
+
+#include "Attribute.h"
+
+#include <new>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "BPlusTree.h"
+#include "CRCTable.h"
+#include "Utility.h"
+
+
+//#define TRACE_BTRFS
+#ifdef TRACE_BTRFS
+#      define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x)
+#else
+#      define TRACE(x...) ;
+#endif
+
+
+Attribute::Attribute(Inode* inode)
+       :
+       fVolume(inode->GetVolume()),
+       fInode(inode),
+       fName(NULL)
+{
+}
+
+
+Attribute::Attribute(Inode* inode, attr_cookie* cookie)
+       :
+       fVolume(inode->GetVolume()),
+       fInode(inode),
+       fName(cookie->name)
+{
+}
+
+
+Attribute::~Attribute()
+{
+}
+
+
+status_t
+Attribute::CheckAccess(const char* name, int openMode)
+{
+       return fInode->CheckPermissions(open_mode_to_access(openMode)
+               | (openMode & O_TRUNC ? W_OK : 0));
+}
+
+
+status_t
+Attribute::Open(const char* name, int openMode, attr_cookie** _cookie)
+{
+       TRACE("Open\n");
+       status_t status = CheckAccess(name, openMode);
+       if (status < B_OK)
+               return status;
+
+       status = _Lookup(name, strlen(name));
+       if (status < B_OK)
+               return status;
+
+       attr_cookie* cookie = new(std::nothrow) attr_cookie;
+       if (cookie == NULL)
+               return B_NO_MEMORY;
+
+       fName = name;
+
+       // initialize the cookie
+       strlcpy(cookie->name, fName, B_ATTR_NAME_LENGTH);
+       cookie->open_mode = openMode;
+       cookie->create = false;
+
+       *_cookie = cookie;
+       return B_OK;
+}
+
+
+status_t
+Attribute::Stat(struct stat& stat)
+{
+       TRACE("Stat\n");
+
+       size_t nameLength = strlen(fName);
+       btrfs_dir_entry *entries;
+       size_t length;
+       status_t status = _Lookup(fName, nameLength, &entries, &length);
+       if (status < B_OK)
+               return status;
+
+       btrfs_dir_entry *entry;
+       status = _FindEntry(entries, length, fName, nameLength, &entry);
+       if (status != B_OK) {
+               free(entries);
+               return status;
+       }
+
+       // found an entry to stat
+       stat.st_type = B_RAW_TYPE;
+       stat.st_size = entry->DataLength();
+       free(entries);
+       return B_OK;
+}
+
+
+status_t
+Attribute::Read(attr_cookie* cookie, off_t pos, uint8* buffer, size_t* _length)
+{
+       if (pos < 0LL)
+               return ERANGE;
+
+       size_t nameLength = strlen(fName);
+       btrfs_dir_entry *entries;
+       size_t length;
+       status_t status = _Lookup(fName, nameLength, &entries, &length);
+       if (status < B_OK)
+               return status;
+
+       btrfs_dir_entry *entry;
+       status = _FindEntry(entries, length, fName, nameLength, &entry);
+       if (status != B_OK) {
+               free(entries);
+               return status;
+       }
+
+       // found an entry to read
+       if (pos + *_length > entry->DataLength())
+               length = entry->DataLength() - pos;
+       else
+               length = *_length - pos;
+       memcpy(buffer, (uint8*)entry + entry->NameLength()
+               + sizeof(btrfs_dir_entry) + (uint32)pos, length);
+       *_length = length;
+
+       free(entries);
+       return B_OK;
+}
+
+
+status_t
+Attribute::_Lookup(const char* name, size_t nameLength,
+       btrfs_dir_entry **_entries, size_t *_length)
+{
+       uint32 hash = calculate_crc((uint32)~1, (uint8*)name, nameLength);
+       struct btrfs_key key;
+       key.SetType(BTRFS_KEY_TYPE_XATTR_ITEM);
+       key.SetObjectID(fInode->ID());
+       key.SetOffset(hash);
+
+       btrfs_dir_entry *entries;
+       size_t length;
+       status_t status = fInode->GetVolume()->FSTree()->FindExact(key,
+               (void**)&entries, &length);
+       if (status != B_OK) {
+               TRACE("AttributeIterator::Lookup(): Couldn't find entry with 
hash %lu "
+                       "\"%s\"\n", hash, name);
+               return status;
+       }
+       
+       if (_entries == NULL)
+               free(entries);
+       else
+               *_entries = entries;
+
+       if (_length != NULL)
+               *_length = length;
+
+       return B_OK;
+}
+
+
+status_t
+Attribute::_FindEntry(btrfs_dir_entry *entries, size_t length,
+       const char* name, size_t nameLength, btrfs_dir_entry **_entry)
+{
+       btrfs_dir_entry *entry = entries;
+       uint16 current = 0;
+       while (current < length) {
+               current += entry->Length();
+               break;
+               // TODO there could be several entries with the same name hash
+               entry = (btrfs_dir_entry *)((uint8*)entry + entry->Length());
+       }
+       
+       *_entry = entry;
+       return B_OK;
+}
+

Added: haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.h               
                (rev 0)
+++ haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Attribute.h       
2011-01-31 19:16:14 UTC (rev 40335)
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
+ * Copyright 2004-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * This file may be used under the terms of the MIT License.
+ */
+#ifndef ATTRIBUTE_H
+#define ATTRIBUTE_H
+
+
+#include "CachedBlock.h"
+#include "Inode.h"
+
+
+struct attr_cookie {
+       char    name[B_ATTR_NAME_LENGTH];
+       uint32  type;
+       int             open_mode;
+       bool    create;
+};
+
+
+class Attribute {
+public:
+                                                               
Attribute(Inode* inode);
+                                                               
Attribute(Inode* inode, attr_cookie* cookie);
+                                                               ~Attribute();
+
+                       status_t                        CheckAccess(const char* 
name, int openMode);
+
+                       status_t                        Create(const char* 
name, type_code type,
+                                                                       int 
openMode, attr_cookie** _cookie);
+                       status_t                        Open(const char* name, 
int openMode,
+                                                                       
attr_cookie** _cookie);
+
+                       status_t                        Stat(struct stat& stat);
+
+                       status_t                        Read(attr_cookie* 
cookie, off_t pos,
+                                                                       uint8* 
buffer, size_t* _length);
+private:
+                       status_t                        _Lookup(const char* 
name, size_t nameLength,
+                                                                       
btrfs_dir_entry **entries = NULL,
+                                                                       size_t 
*length = NULL);
+                       status_t                        
_FindEntry(btrfs_dir_entry *entries,
+                                                                       size_t 
length, const char* name,
+                                                                       size_t 
nameLength,
+                                                                       
btrfs_dir_entry **_entry);
+
+                       ::Volume*                       fVolume;
+                       Inode*                          fInode;
+                       const char*                     fName;
+};
+
+#endif // ATTRIBUTE_H
+

Added: haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp     
                        (rev 0)
+++ haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp     
2011-01-31 19:16:14 UTC (rev 40335)
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
+ * This file may be used under the terms of the MIT License.
+ */
+
+
+#include "AttributeIterator.h"
+
+#include <new>
+#include <stdlib.h>
+
+
+//#define TRACE_BTRFS
+#ifdef TRACE_BTRFS
+#      define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x)
+#else
+#      define TRACE(x...) ;
+#endif
+#      define ERROR(x...) dprintf("\33[34mbtrfs:\33[0m " x)
+
+
+AttributeIterator::AttributeIterator(Inode* inode)
+       :
+       fOffset(-1ULL),
+       fInode(inode),
+       fIterator(NULL)
+{
+       struct btrfs_key key;
+       key.SetType(BTRFS_KEY_TYPE_XATTR_ITEM);
+       key.SetObjectID(inode->ID());
+       fIterator = new(std::nothrow) TreeIterator(inode->GetVolume()->FSTree(),
+               key);
+}
+
+
+AttributeIterator::~AttributeIterator()
+{
+       delete fIterator;
+}
+
+
+status_t
+AttributeIterator::InitCheck()
+{
+       return fIterator != NULL ? B_OK : B_NO_MEMORY;
+}
+
+
+status_t
+AttributeIterator::GetNext(char* name, size_t* _nameLength)
+{
+       btrfs_key key;
+       btrfs_dir_entry *entries;
+       size_t entries_length;
+       status_t status = fIterator->GetPreviousEntry(key, (void**)&entries,
+               &entries_length);
+       if (status != B_OK)
+               return status;
+
+       btrfs_dir_entry *entry = entries;
+       uint16 current = 0;
+       while (current < entries_length) {
+               current += entry->Length();
+               break;
+               // TODO there could be several entries with the same name hash
+               entry = (btrfs_dir_entry *)((uint8*)entry + entry->Length());
+       }
+
+       TRACE("DirectoryIterator::GetNext() entries_length %ld name_length 
%d\n",
+               entries_length, entry->NameLength());
+
+       memcpy(name, entry + 1, entry->NameLength());
+       name[entry->NameLength()] = '\0';
+       *_nameLength = entry->NameLength();
+       free(entries);
+
+       return B_OK;
+}
+
+
+status_t
+AttributeIterator::Rewind()
+{
+       fIterator->Rewind();
+       fOffset = -1ULL;
+       return B_OK;
+}
+

Added: haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.h       
                        (rev 0)
+++ haiku/trunk/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.h       
2011-01-31 19:16:14 UTC (rev 40335)
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
+ * This file may be used under the terms of the MIT License.
+ */
+#ifndef ATTRIBUTEITERATOR_H
+#define ATTRIBUTEITERATOR_H
+
+
+#include "BPlusTree.h"
+#include "Inode.h"
+
+
+class AttributeIterator {
+public:
+                                                               
AttributeIterator(Inode* inode);
+                                                               
~AttributeIterator();
+
+                       status_t                        InitCheck();
+
+                       status_t                        GetNext(char* name, 
size_t* _nameLength);
+                       status_t                        Rewind();
+private:
+                       uint64                          fOffset;
+                       Inode*                          fInode;
+                       TreeIterator*           fIterator;
+};
+
+
+#endif // ATTRIBUTEITERATOR_H

Modified: haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Jamfile   2011-01-31 
18:29:20 UTC (rev 40334)
+++ haiku/trunk/src/add-ons/kernel/file_systems/btrfs/Jamfile   2011-01-31 
19:16:14 UTC (rev 40335)
@@ -6,6 +6,8 @@
 
 KernelAddon btrfs :
        kernel_interface.cpp
+       Attribute.cpp
+       AttributeIterator.cpp
        BPlusTree.cpp
        Chunk.cpp
        CRCTable.cpp

Modified: haiku/trunk/src/add-ons/kernel/file_systems/btrfs/btrfs.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/btrfs/btrfs.h   2011-01-31 
18:29:20 UTC (rev 40334)
+++ haiku/trunk/src/add-ons/kernel/file_systems/btrfs/btrfs.h   2011-01-31 
19:16:14 UTC (rev 40335)
@@ -308,6 +308,7 @@
 #define BTRFS_KEY_TYPE_INODE_ITEM              1
 #define BTRFS_KEY_TYPE_INODE_REF               12
 #define BTRFS_KEY_TYPE_ROOT_ITEM               132
+#define BTRFS_KEY_TYPE_XATTR_ITEM              24
 
 #define BTRFS_EXTENT_DATA_INLINE               0
 #define BTRFS_EXTENT_DATA_REGULAR              1

Modified: haiku/trunk/src/add-ons/kernel/file_systems/btrfs/kernel_interface.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/btrfs/kernel_interface.cpp      
2011-01-31 18:29:20 UTC (rev 40334)
+++ haiku/trunk/src/add-ons/kernel/file_systems/btrfs/kernel_interface.cpp      
2011-01-31 19:16:14 UTC (rev 40335)
@@ -16,6 +16,8 @@
 #include <NodeMonitor.h>
 #include <util/AutoLock.h>
 
+#include "Attribute.h"
+#include "AttributeIterator.h"
 #include "btrfs.h"
 #include "DirectoryIterator.h"
 #include "Inode.h"
@@ -291,7 +293,6 @@
        size_t size, struct file_io_vec* vecs, size_t* _count)
 {
        TRACE("btrfs_get_file_map()\n");
-       Volume* volume = (Volume*)_volume->private_volume;
        Inode* inode = (Inode*)_node->private_node;
        size_t index = 0, max = *_count;
 
@@ -563,6 +564,177 @@
 }
 
 
+static status_t
+btrfs_open_attr_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie)
+{
+       Inode* inode = (Inode*)_node->private_node;
+       TRACE("%s()\n", __FUNCTION__);
+
+       // on directories too ?
+       if (!inode->IsFile())
+               return EINVAL;
+
+       AttributeIterator* iterator = new(std::nothrow) 
AttributeIterator(inode);
+       if (iterator == NULL || iterator->InitCheck() != B_OK) {
+               delete iterator;
+               return B_NO_MEMORY;
+       }
+
+       *_cookie = iterator;
+       return B_OK;
+}
+
+
+static status_t
+btrfs_close_attr_dir(fs_volume* _volume, fs_vnode* _node, void* cookie)
+{
+       TRACE("%s()\n", __FUNCTION__);
+       return B_OK;
+}
+
+
+static status_t
+btrfs_free_attr_dir_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
+{
+       TRACE("%s()\n", __FUNCTION__);
+       delete (AttributeIterator*)_cookie;
+       return B_OK;
+}
+
+
+static status_t
+btrfs_read_attr_dir(fs_volume* _volume, fs_vnode* _node,
+                               void* _cookie, struct dirent* dirent, size_t 
bufferSize,
+                               uint32* _num)
+{
+       TRACE("%s()\n", __FUNCTION__);
+       AttributeIterator* iterator = (AttributeIterator*)_cookie;
+
+       size_t length = bufferSize;
+       status_t status = iterator->GetNext(dirent->d_name, &length);
+       if (status == B_ENTRY_NOT_FOUND) {
+               *_num = 0;
+               return B_OK;
+       } else if (status != B_OK)
+               return status;
+
+       Volume* volume = (Volume*)_volume->private_volume;
+       dirent->d_dev = volume->ID();
+       dirent->d_reclen = sizeof(struct dirent) + length;
+       *_num = 1;
+
+       return B_OK;
+}
+
+
+static status_t
+btrfs_rewind_attr_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie)
+{
+       DirectoryIterator* iterator = (DirectoryIterator*)_cookie;
+       return iterator->Rewind();
+}
+
+
+       /* attribute operations */
+static status_t
+btrfs_create_attr(fs_volume* _volume, fs_vnode* _node,
+       const char* name, uint32 type, int openMode, void** _cookie)
+{
+       return EROFS;
+}
+
+
+static status_t
+btrfs_open_attr(fs_volume* _volume, fs_vnode* _node, const char* name,
+       int openMode, void** _cookie)
+{
+       TRACE("%s()\n", __FUNCTION__);
+
+       Inode* inode = (Inode*)_node->private_node;
+       Attribute attribute(inode);
+
+       return attribute.Open(name, openMode, (attr_cookie**)_cookie);
+}
+
+
+static status_t
+btrfs_close_attr(fs_volume* _volume, fs_vnode* _node,
+       void* cookie)
+{
+       return B_OK;
+}
+
+
+static status_t
+btrfs_free_attr_cookie(fs_volume* _volume, fs_vnode* _node,
+       void* cookie)
+{
+       delete (attr_cookie*)cookie;
+       return B_OK;
+}
+
+
+static status_t
+btrfs_read_attr(fs_volume* _volume, fs_vnode* _node, void* _cookie,
+       off_t pos, void* buffer, size_t* _length)
+{
+       TRACE("%s()\n", __FUNCTION__);
+
+       attr_cookie* cookie = (attr_cookie*)_cookie;
+       Inode* inode = (Inode*)_node->private_node;
+
+       Attribute attribute(inode, cookie);
+
+       return attribute.Read(cookie, pos, (uint8*)buffer, _length);
+}
+
+
+static status_t
+btrfs_write_attr(fs_volume* _volume, fs_vnode* _node, void* cookie,
+       off_t pos, const void* buffer, size_t* length)
+{
+       return EROFS;
+}
+
+
+
+static status_t
+btrfs_read_attr_stat(fs_volume* _volume, fs_vnode* _node,
+       void* _cookie, struct stat* stat)
+{
+       attr_cookie* cookie = (attr_cookie*)_cookie;
+       Inode* inode = (Inode*)_node->private_node;
+
+       Attribute attribute(inode, cookie);
+
+       return attribute.Stat(*stat);
+}
+
+
+static status_t
+btrfs_write_attr_stat(fs_volume* _volume, fs_vnode* _node,
+       void* cookie, const struct stat* stat, int statMask)
+{
+       return EROFS;
+}
+
+
+static status_t
+btrfs_rename_attr(fs_volume* _volume, fs_vnode* fromVnode,
+       const char* fromName, fs_vnode* toVnode, const char* toName)
+{
+       return EROFS;
+}
+
+
+static status_t
+btrfs_remove_attr(fs_volume* _volume, fs_vnode* vnode,
+       const char* name)
+{
+       return EROFS;
+}
+
+
 fs_volume_ops gBtrfsVolumeOps = {
        &btrfs_unmount,
        &btrfs_read_fs_info,
@@ -625,23 +797,23 @@
        &btrfs_rewind_dir,
 
        /* attribute directory operations */
-       NULL,   // fs_open_attr_dir,
-       NULL,   // fs_close_attr_dir,
-       NULL,   // fs_free_attr_dir_cookie,
-       NULL,   // fs_read_attr_dir,
-       NULL,   // fs_rewind_attr_dir,
+       &btrfs_open_attr_dir,
+       &btrfs_close_attr_dir,
+       &btrfs_free_attr_dir_cookie,
+       &btrfs_read_attr_dir,
+       &btrfs_rewind_attr_dir,
 
        /* attribute operations */
-       NULL,   // fs_create_attr,
-       NULL,   // fs_open_attr,
-       NULL,   // fs_close_attr,
-       NULL,   // fs_free_attr_cookie,
-       NULL,   // fs_read_attr,
-       NULL,   // fs_write_attr,
-       NULL,   // fs_read_attr_stat,
-       NULL,   // fs_write_attr_stat,
-       NULL,   // fs_rename_attr,
-       NULL,   // fs_remove_attr,
+       &btrfs_create_attr,
+       &btrfs_open_attr,
+       &btrfs_close_attr,
+       &btrfs_free_attr_cookie,
+       &btrfs_read_attr,
+       &btrfs_write_attr,
+       &btrfs_read_attr_stat,
+       &btrfs_write_attr_stat,
+       &btrfs_rename_attr,
+       &btrfs_remove_attr,
 };
 
 


Other related posts: