Split overlay filesystem into attribute_overlay and write_overlay.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29255 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -34,24 +34,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
namespace overlay {
|
||||
namespace attribute_overlay {
|
||||
|
||||
class AttributeFile;
|
||||
class AttributeEntry;
|
||||
|
||||
|
||||
struct open_cookie {
|
||||
int open_mode;
|
||||
void * super_cookie;
|
||||
};
|
||||
|
||||
struct write_buffer {
|
||||
write_buffer * next;
|
||||
off_t position;
|
||||
size_t length;
|
||||
uint8 buffer[1];
|
||||
};
|
||||
|
||||
struct attribute_dir_cookie {
|
||||
AttributeFile * file;
|
||||
uint32 index;
|
||||
@@ -63,16 +51,11 @@ public:
|
||||
OverlayVolume(fs_volume *volume);
|
||||
~OverlayVolume();
|
||||
|
||||
status_t AllLayersMounted();
|
||||
|
||||
fs_volume * Volume() { return fVolume; }
|
||||
fs_volume * SuperVolume() { return fVolume->super_volume; }
|
||||
|
||||
bool WriteSupport() { return fWriteSupport; }
|
||||
|
||||
private:
|
||||
fs_volume * fVolume;
|
||||
bool fWriteSupport;
|
||||
};
|
||||
|
||||
|
||||
@@ -92,25 +75,11 @@ public:
|
||||
status_t GetAttributeFile(AttributeFile **attributeFile);
|
||||
status_t WriteAttributeFile();
|
||||
|
||||
status_t ReadStat(struct stat *stat);
|
||||
|
||||
status_t Open(int openMode, void **cookie);
|
||||
status_t Close(void *cookie);
|
||||
status_t FreeCookie(void *cookie);
|
||||
status_t Read(void *cookie, off_t position, void *buffer,
|
||||
size_t *length);
|
||||
status_t Write(void *cookie, off_t position,
|
||||
const void *buffer, size_t *length);
|
||||
|
||||
private:
|
||||
OverlayVolume * fVolume;
|
||||
fs_vnode fSuperVnode;
|
||||
ino_t fInodeNumber;
|
||||
AttributeFile * fAttributeFile;
|
||||
write_buffer * fWriteBuffers;
|
||||
off_t fOriginalNodeLength;
|
||||
off_t fCurrentNodeLength;
|
||||
time_t fModificationTime;
|
||||
};
|
||||
|
||||
|
||||
@@ -223,8 +192,7 @@ private:
|
||||
|
||||
|
||||
OverlayVolume::OverlayVolume(fs_volume *volume)
|
||||
: fVolume(volume),
|
||||
fWriteSupport(false)
|
||||
: fVolume(volume)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -234,19 +202,6 @@ OverlayVolume::~OverlayVolume()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OverlayVolume::AllLayersMounted()
|
||||
{
|
||||
fs_info info;
|
||||
fs_volume *superVolume = fVolume->super_volume;
|
||||
if (superVolume->ops->read_fs_info != NULL
|
||||
&& superVolume->ops->read_fs_info(superVolume, &info) == B_OK)
|
||||
fWriteSupport = (info.flags & B_FS_IS_READONLY) != 0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark OverlayInode
|
||||
|
||||
|
||||
@@ -255,10 +210,7 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode,
|
||||
: fVolume(volume),
|
||||
fSuperVnode(*superVnode),
|
||||
fInodeNumber(inodeNumber),
|
||||
fAttributeFile(NULL),
|
||||
fWriteBuffers(NULL),
|
||||
fOriginalNodeLength(-1),
|
||||
fCurrentNodeLength(-1)
|
||||
fAttributeFile(NULL)
|
||||
{
|
||||
TRACE("inode created\n");
|
||||
}
|
||||
@@ -268,13 +220,6 @@ OverlayInode::~OverlayInode()
|
||||
{
|
||||
TRACE("inode destroyed\n");
|
||||
delete fAttributeFile;
|
||||
|
||||
write_buffer *element = fWriteBuffers;
|
||||
while (element) {
|
||||
write_buffer *next = element->next;
|
||||
free(element);
|
||||
element = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -329,238 +274,6 @@ OverlayInode::WriteAttributeFile()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OverlayInode::ReadStat(struct stat *stat)
|
||||
{
|
||||
if (fSuperVnode.ops->read_stat == NULL)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
status_t result = fSuperVnode.ops->read_stat(SuperVolume(), &fSuperVnode,
|
||||
stat);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (fVolume->WriteSupport() && fCurrentNodeLength >= 0) {
|
||||
stat->st_size = fCurrentNodeLength;
|
||||
stat->st_blocks = (stat->st_size + stat->st_blksize - 1)
|
||||
/ stat->st_blksize;
|
||||
stat->st_mtime = fModificationTime;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OverlayInode::Open(int openMode, void **_cookie)
|
||||
{
|
||||
if (fSuperVnode.ops->open == NULL)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
if (fVolume->WriteSupport()) {
|
||||
open_cookie *cookie = (open_cookie *)malloc(sizeof(open_cookie));
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (fOriginalNodeLength < 0) {
|
||||
struct stat stat;
|
||||
status_t result = fSuperVnode.ops->read_stat(SuperVolume(),
|
||||
&fSuperVnode, &stat);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
fOriginalNodeLength = stat.st_size;
|
||||
fCurrentNodeLength = stat.st_size;
|
||||
fModificationTime = stat.st_mtime;
|
||||
}
|
||||
|
||||
cookie->open_mode = openMode;
|
||||
*_cookie = cookie;
|
||||
|
||||
if (openMode & O_TRUNC)
|
||||
fCurrentNodeLength = 0;
|
||||
|
||||
openMode &= ~(O_RDWR | O_WRONLY | O_TRUNC | O_CREAT);
|
||||
return fSuperVnode.ops->open(SuperVolume(), &fSuperVnode, openMode,
|
||||
&cookie->super_cookie);
|
||||
}
|
||||
|
||||
return fSuperVnode.ops->open(SuperVolume(), &fSuperVnode, openMode,
|
||||
_cookie);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OverlayInode::Close(void *_cookie)
|
||||
{
|
||||
if (fVolume->WriteSupport()) {
|
||||
open_cookie *cookie = (open_cookie *)_cookie;
|
||||
return fSuperVnode.ops->close(SuperVolume(), &fSuperVnode,
|
||||
cookie->super_cookie);
|
||||
}
|
||||
|
||||
return fSuperVnode.ops->close(SuperVolume(), &fSuperVnode, _cookie);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OverlayInode::FreeCookie(void *_cookie)
|
||||
{
|
||||
if (fVolume->WriteSupport()) {
|
||||
open_cookie *cookie = (open_cookie *)_cookie;
|
||||
status_t result = fSuperVnode.ops->free_cookie(SuperVolume(),
|
||||
&fSuperVnode, cookie->super_cookie);
|
||||
free(cookie);
|
||||
return result;
|
||||
}
|
||||
|
||||
return fSuperVnode.ops->free_cookie(SuperVolume(), &fSuperVnode, _cookie);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length)
|
||||
{
|
||||
if (fVolume->WriteSupport()) {
|
||||
if (position >= fCurrentNodeLength) {
|
||||
*length = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (position < fOriginalNodeLength) {
|
||||
open_cookie *cookie = (open_cookie *)_cookie;
|
||||
size_t readLength = MIN(fOriginalNodeLength - position, *length);
|
||||
status_t result = fSuperVnode.ops->read(SuperVolume(), &fSuperVnode,
|
||||
cookie->super_cookie, position, buffer, &readLength);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
// overlay the read with whatever chunks we have written
|
||||
write_buffer *element = fWriteBuffers;
|
||||
*length = MIN(fCurrentNodeLength - position, *length);
|
||||
off_t end = position + *length;
|
||||
while (element) {
|
||||
if (element->position > end)
|
||||
break;
|
||||
|
||||
off_t elementEnd = element->position + element->length;
|
||||
if (elementEnd > position) {
|
||||
off_t copyPosition = MAX(position, element->position);
|
||||
size_t copyLength = MIN(elementEnd - position, *length);
|
||||
memcpy((uint8 *)buffer + (copyPosition - position),
|
||||
element->buffer + (copyPosition - element->position),
|
||||
copyLength);
|
||||
}
|
||||
|
||||
element = element->next;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return fSuperVnode.ops->read(SuperVolume(), &fSuperVnode, _cookie,
|
||||
position, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
|
||||
size_t *length)
|
||||
{
|
||||
if (fVolume->WriteSupport()) {
|
||||
// find insertion point
|
||||
write_buffer **link = &fWriteBuffers;
|
||||
write_buffer *other = fWriteBuffers;
|
||||
write_buffer *swallow = NULL;
|
||||
off_t newPosition = position;
|
||||
size_t newLength = *length;
|
||||
uint32 swallowCount = 0;
|
||||
|
||||
while (other) {
|
||||
off_t newEnd = newPosition + newLength;
|
||||
off_t otherEnd = other->position + other->length;
|
||||
if (otherEnd < newPosition) {
|
||||
// other is completely before us
|
||||
link = &other->next;
|
||||
other = other->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (other->position > newEnd) {
|
||||
// other is completely past us
|
||||
break;
|
||||
}
|
||||
|
||||
swallowCount++;
|
||||
if (swallow == NULL)
|
||||
swallow = other;
|
||||
|
||||
if (other->position <= newPosition) {
|
||||
if (swallowCount == 1 && otherEnd >= newEnd) {
|
||||
// other chunk completely covers us, just copy
|
||||
memcpy(other->buffer + (newPosition - other->position),
|
||||
buffer, *length);
|
||||
|
||||
fModificationTime = time(NULL);
|
||||
notify_stat_changed(SuperVolume()->id, fInodeNumber,
|
||||
B_STAT_MODIFICATION_TIME);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
newLength += newPosition - other->position;
|
||||
newPosition = other->position;
|
||||
}
|
||||
|
||||
if (otherEnd > newEnd)
|
||||
newLength += otherEnd - newEnd;
|
||||
|
||||
other = other->next;
|
||||
}
|
||||
|
||||
write_buffer *element = (write_buffer *)malloc(sizeof(write_buffer) - 1
|
||||
+ newLength);
|
||||
if (element == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
element->next = *link;
|
||||
element->position = newPosition;
|
||||
element->length = newLength;
|
||||
*link = element;
|
||||
|
||||
bool sizeChanged = false;
|
||||
off_t newEnd = newPosition + newLength;
|
||||
if (newEnd > fCurrentNodeLength) {
|
||||
fCurrentNodeLength = newEnd;
|
||||
sizeChanged = true;
|
||||
}
|
||||
|
||||
// populate the buffer with the existing chunks
|
||||
if (swallowCount > 0) {
|
||||
while (swallowCount-- > 0) {
|
||||
memcpy(element->buffer + (swallow->position - newPosition),
|
||||
swallow->buffer, swallow->length);
|
||||
|
||||
element->next = swallow->next;
|
||||
free(swallow);
|
||||
swallow = element->next;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(element->buffer + (position - newPosition), buffer, *length);
|
||||
|
||||
fModificationTime = time(NULL);
|
||||
notify_stat_changed(SuperVolume()->id, fInodeNumber,
|
||||
B_STAT_MODIFICATION_TIME | (sizeChanged ? B_STAT_SIZE : 0));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return fSuperVnode.ops->write(SuperVolume(), &fSuperVnode, _cookie,
|
||||
position, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark AttributeFile
|
||||
|
||||
|
||||
@@ -1510,7 +1223,8 @@ overlay_access(fs_volume *volume, fs_vnode *vnode, int mode)
|
||||
static status_t
|
||||
overlay_read_stat(fs_volume *volume, fs_vnode *vnode, struct stat *stat)
|
||||
{
|
||||
return ((OverlayInode *)vnode->private_node)->ReadStat(stat);
|
||||
OVERLAY_CALL(read_stat, stat)
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -1535,21 +1249,24 @@ overlay_create(fs_volume *volume, fs_vnode *vnode, const char *name,
|
||||
static status_t
|
||||
overlay_open(fs_volume *volume, fs_vnode *vnode, int openMode, void **cookie)
|
||||
{
|
||||
return ((OverlayInode *)vnode->private_node)->Open(openMode, cookie);
|
||||
OVERLAY_CALL(open, openMode, cookie)
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
overlay_close(fs_volume *volume, fs_vnode *vnode, void *cookie)
|
||||
{
|
||||
return ((OverlayInode *)vnode->private_node)->Close(cookie);
|
||||
OVERLAY_CALL(close, cookie)
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
overlay_free_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
|
||||
{
|
||||
return ((OverlayInode *)vnode->private_node)->FreeCookie(cookie);
|
||||
OVERLAY_CALL(free_cookie, cookie)
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -1557,8 +1274,8 @@ static status_t
|
||||
overlay_read(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
|
||||
void *buffer, size_t *length)
|
||||
{
|
||||
return ((OverlayInode *)vnode->private_node)->Read(cookie, pos, buffer,
|
||||
length);
|
||||
OVERLAY_CALL(read, cookie, pos, buffer, length)
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -1566,8 +1283,8 @@ static status_t
|
||||
overlay_write(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
|
||||
const void *buffer, size_t *length)
|
||||
{
|
||||
return ((OverlayInode *)vnode->private_node)->Write(cookie, pos, buffer,
|
||||
length);
|
||||
OVERLAY_CALL(write, cookie, pos, buffer, length)
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -1759,8 +1476,7 @@ overlay_read_attr(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
|
||||
void *buffer, size_t *length)
|
||||
{
|
||||
OVERLAY_CALL(read_attr, cookie, pos, buffer, length)
|
||||
AttributeEntry *entry = (AttributeEntry *)cookie;
|
||||
return entry->Read(pos, buffer, length);
|
||||
return ((AttributeEntry *)cookie)->Read(pos, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
@@ -1769,8 +1485,7 @@ overlay_write_attr(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
|
||||
const void *buffer, size_t *length)
|
||||
{
|
||||
OVERLAY_CALL(write_attr, cookie, pos, buffer, length)
|
||||
AttributeEntry *entry = (AttributeEntry *)cookie;
|
||||
return entry->Write(pos, buffer, length);
|
||||
return ((AttributeEntry *)cookie)->Write(pos, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
@@ -1779,8 +1494,7 @@ overlay_read_attr_stat(fs_volume *volume, fs_vnode *vnode, void *cookie,
|
||||
struct stat *stat)
|
||||
{
|
||||
OVERLAY_CALL(read_attr_stat, cookie, stat)
|
||||
AttributeEntry *entry = (AttributeEntry *)cookie;
|
||||
return entry->ReadStat(stat);
|
||||
return ((AttributeEntry *)cookie)->ReadStat(stat);
|
||||
}
|
||||
|
||||
|
||||
@@ -1789,8 +1503,7 @@ overlay_write_attr_stat(fs_volume *volume, fs_vnode *vnode, void *cookie,
|
||||
const struct stat *stat, int statMask)
|
||||
{
|
||||
OVERLAY_CALL(write_attr_stat, cookie, stat, statMask)
|
||||
AttributeEntry *entry = (AttributeEntry *)cookie;
|
||||
return entry->WriteStat(stat, statMask);
|
||||
return ((AttributeEntry *)cookie)->WriteStat(stat, statMask);
|
||||
}
|
||||
|
||||
|
||||
@@ -1973,9 +1686,6 @@ overlay_read_fs_info(fs_volume *volume, struct fs_info *info)
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
OverlayVolume *overlayVolume = (OverlayVolume *)volume->private_volume;
|
||||
if (overlayVolume->WriteSupport())
|
||||
info->flags &= ~B_FS_IS_READONLY;
|
||||
info->flags |= B_FS_HAS_MIME | B_FS_HAS_ATTR /*| B_FS_HAS_QUERY*/;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -2147,7 +1857,7 @@ overlay_rewind_query(fs_volume *volume, void *cookie)
|
||||
static status_t
|
||||
overlay_all_layers_mounted(fs_volume *volume)
|
||||
{
|
||||
return ((OverlayVolume *)volume->private_volume)->AllLayersMounted();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -2241,14 +1951,14 @@ overlay_std_ops(int32 op, ...)
|
||||
|
||||
static file_system_module_info sOverlayFileSystem = {
|
||||
{
|
||||
"file_systems/overlay"B_CURRENT_FS_API_VERSION,
|
||||
"file_systems/attribute_overlay"B_CURRENT_FS_API_VERSION,
|
||||
0,
|
||||
overlay_std_ops,
|
||||
},
|
||||
|
||||
"overlay", // short_name
|
||||
"Overlay File System", // pretty_name
|
||||
0, // DDM flags
|
||||
"attribute_overlay", // short_name
|
||||
"Attribute Overlay File System", // pretty_name
|
||||
0, // DDM flags
|
||||
|
||||
// scanning
|
||||
NULL, // identify_partition
|
||||
@@ -2281,9 +1991,9 @@ static file_system_module_info sOverlayFileSystem = {
|
||||
NULL // initialize
|
||||
};
|
||||
|
||||
} // namespace _overlay
|
||||
} // namespace attribute_overlay
|
||||
|
||||
using namespace overlay;
|
||||
using namespace attribute_overlay;
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&sOverlayFileSystem,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user