Author: axeld Date: 2009-10-29 19:09:15 +0100 (Thu, 29 Oct 2009) New Revision: 33832 Changeset: http://dev.haiku-os.org/changeset/33832/haiku Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.cpp haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.h haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.cpp haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.h haiku/trunk/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp Log: * Improved the status_change time check to actually filter out invalid times, before, st_ctim was never updated; since you cannot change st_ctim via an API, '0' cannot ever be set, either. * Inode::WriteAttribute(), and Attribute::Write() now return whether they created an attribute or not, and thus B_ATTR_CREATED is now correctly set. * Moved status_change update from bfs_write_attr() into Inode::WriteAttribute() where it can be handled more efficiently. * Likewise, Inode::RemoveAttribute() now updates the status_change time as well, I simply forgot this before. * Minor cleanup. Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.cpp 2009-10-29 17:50:56 UTC (rev 33831) +++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.cpp 2009-10-29 18:09:15 UTC (rev 33832) @@ -205,13 +205,13 @@ status_t Attribute::Write(Transaction& transaction, attr_cookie* cookie, off_t pos, - const uint8* buffer, size_t* _length) + const uint8* buffer, size_t* _length, bool* _created) { if (!cookie->create && fSmall == NULL && fAttribute == NULL) return B_NO_INIT; return fInode->WriteAttribute(transaction, cookie->name, cookie->type, - pos, buffer, _length); + pos, buffer, _length, _created); } Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.h 2009-10-29 17:50:56 UTC (rev 33831) +++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/Attribute.h 2009-10-29 18:09:15 UTC (rev 33832) @@ -39,8 +39,8 @@ status_t Read(attr_cookie* cookie, off_t pos, uint8* buffer, size_t* _length); status_t Write(Transaction& transaction, attr_cookie* cookie, - off_t pos, const uint8* buffer, - size_t* _length); + off_t pos, const uint8* buffer, size_t* _length, + bool* _created); private: status_t _Truncate(); Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.cpp 2009-10-29 17:50:56 UTC (rev 33831) +++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.cpp 2009-10-29 18:09:15 UTC (rev 33832) @@ -650,8 +650,12 @@ nodeGetter.MakeWritable(transaction); status_t status = _RemoveSmallData(node, item, index); - if (status == B_OK) + if (status == B_OK) { + Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64( + bfs_inode::ToInode(real_time_clock_usecs())); + status = WriteBack(transaction); + } return status; } @@ -1033,7 +1037,7 @@ */ status_t Inode::WriteAttribute(Transaction& transaction, const char* name, int32 type, - off_t pos, const uint8* buffer, size_t* _length) + off_t pos, const uint8* buffer, size_t* _length, bool* _created) { if (pos < 0) return B_BAD_VALUE; @@ -1042,6 +1046,7 @@ uint8 oldBuffer[BPLUSTREE_MAX_KEY_LENGTH]; uint8* oldData = NULL; size_t oldLength = 0; + bool created = false; // TODO: we actually depend on that the contents of "buffer" are constant. // If they get changed during the write (hey, user programs), we may mess @@ -1071,7 +1076,9 @@ oldLength = BPLUSTREE_MAX_KEY_LENGTH; memcpy(oldData = oldBuffer, smallData->Data(), oldLength); } - } + } else + created = true; + recursive_lock_unlock(&fSmallDataLock); // if the attribute doesn't exist yet (as a file), try to put it in the @@ -1091,8 +1098,15 @@ status = CreateAttribute(transaction, name, type, &attribute); if (status != B_OK) RETURN_ERROR(status); - } else if (status == B_OK) + + created = true; + } else if (status == B_OK) { + // Update status time on attribute write + Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64( + bfs_inode::ToInode(real_time_clock_usecs())); + status = WriteBack(transaction); + } } if (attribute != NULL) { @@ -1127,6 +1141,14 @@ _length); } } + + if (status == B_OK) { + // Update status time on attribute write + Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64( + bfs_inode::ToInode(real_time_clock_usecs())); + + status = WriteBack(transaction); + } } else status = B_ERROR; @@ -1149,6 +1171,10 @@ length, this); } } + + if (_created != NULL) + *_created = created; + return status; } @@ -1182,7 +1208,13 @@ if (status == B_ENTRY_NOT_FOUND && !Attributes().IsZero()) { // remove the attribute file if it exists status = _RemoveAttribute(transaction, name, hasIndex, &index); + if (status == B_OK) { + Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64( + bfs_inode::ToInode(real_time_clock_usecs())); + WriteBack(transaction); + } } + return status; } Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.h 2009-10-29 17:50:56 UTC (rev 33831) +++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/Inode.h 2009-10-29 18:09:15 UTC (rev 33832) @@ -107,7 +107,8 @@ off_t pos, uint8* buffer, size_t* _length); status_t WriteAttribute(Transaction& transaction, const char* name, int32 type, off_t pos, - const uint8* buffer, size_t* _length); + const uint8* buffer, size_t* _length, + bool* _created); status_t RemoveAttribute(Transaction& transaction, const char* name); Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp 2009-10-29 17:50:56 UTC (rev 33831) +++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp 2009-10-29 18:09:15 UTC (rev 33832) @@ -43,15 +43,9 @@ stat.st_crtim.tv_sec = bfs_inode::ToSecs(node.CreateTime()); stat.st_crtim.tv_nsec = bfs_inode::ToUsecs(node.CreateTime()); - // if on-disk ctime is invalid (pointer value from previous [ab]use of - // the first 4 bytes) or 0, fall back to mtime: - // N.B.: This has the drawback that explicitly setting a ctime of 0 - // will not work, but I suppose no one will do that, since ctime - // is usually just set to the current time whenever something happens - // to the inode. - // TODO: find out if this sanity check should be dropped! + // For BeOS compatibility, if on-disk ctime is invalid, fall back to mtime: bigtime_t changeTime = node.StatusChangeTime(); - if (((uint64)changeTime & 0xFFFF00000000FFFFULL) != 0 || changeTime == 0) + if (changeTime < node.LastModifiedTime()) stat.st_ctim = stat.st_mtim; else { stat.st_ctim.tv_sec = bfs_inode::ToSecs(changeTime); @@ -1196,11 +1190,10 @@ } } - if (newDirectory != oldDirectory) { - oldDirectory->ContainerContentsChanged(transaction); - newDirectory->ContainerContentsChanged(transaction); - } else - newDirectory->ContainerContentsChanged(transaction); + if (status == B_OK && newDirectory != oldDirectory) + status = oldDirectory->ContainerContentsChanged(transaction); + if (status == B_OK) + status = newDirectory->ContainerContentsChanged(transaction); if (status == B_OK) status = inode->WriteBack(transaction); @@ -1808,20 +1801,14 @@ Transaction transaction(volume, inode->BlockNumber()); Attribute attribute(inode, cookie); + bool created; status_t status = attribute.Write(transaction, cookie, pos, - (const uint8*)buffer, _length); + (const uint8*)buffer, _length, &created); if (status == B_OK) { - // Update status time on attribute write - inode->Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64( - bfs_inode::ToInode(real_time_clock_usecs())); - inode->WriteBack(transaction); - status = transaction.Done(); if (status == B_OK) { notify_attribute_changed(volume->ID(), inode->ID(), cookie->name, - B_ATTR_CHANGED); - // TODO: B_ATTR_CREATED is not yet taken into account - // (we don't know what Attribute::Write() does exactly) + created ? B_ATTR_CREATED : B_ATTR_CHANGED); notify_stat_changed(volume->ID(), inode->ID(), B_STAT_CHANGE_TIME); } } @@ -1877,7 +1864,7 @@ Inode* inode = (Inode*)_node->private_node; status_t status = inode->CheckPermissions(W_OK); - if (status < B_OK) + if (status != B_OK) return status; Transaction transaction(volume, inode->BlockNumber());