nfs4: update vnode objects and cached data when rename overrides a file
* this patch also fixes unnecessary cache invalidation when a file is renamed without changing its parent directory
This commit is contained in:
parent
4c2a56efe8
commit
efc29cc57a
@ -311,7 +311,7 @@ Inode::Remove(const char* name, FileType type, ino_t* id)
|
||||
|
||||
status_t
|
||||
Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName,
|
||||
bool attribute, ino_t* id)
|
||||
bool attribute, ino_t* id, ino_t* oldID)
|
||||
{
|
||||
ASSERT(from != NULL);
|
||||
ASSERT(fromName != NULL);
|
||||
@ -341,8 +341,12 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName,
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
ChangeInfo fromChange, toChange;
|
||||
uint64 oldFileID = 0;
|
||||
if (!attribute)
|
||||
to->NFS4Inode::LookUp(toName, NULL, &oldFileID, NULL);
|
||||
|
||||
uint64 fileID;
|
||||
ChangeInfo fromChange, toChange;
|
||||
status_t result = NFS4Inode::RenameNode(from, to, fromName, toName,
|
||||
&fromChange, &toChange, &fileID, attribute);
|
||||
if (result != B_OK)
|
||||
@ -350,32 +354,37 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName,
|
||||
|
||||
from->fFileSystem->Root()->MakeInfoInvalid();
|
||||
|
||||
if (id != NULL)
|
||||
*id = FileIdToInoT(fileID);
|
||||
if (oldID != NULL)
|
||||
*oldID = FileIdToInoT(oldFileID);
|
||||
|
||||
DirectoryCache* cache = attribute ? from->fAttrCache : from->fCache;
|
||||
cache->Lock();
|
||||
if (cache->Valid()) {
|
||||
if (fromChange.fAtomic
|
||||
&& cache->ChangeInfo() == fromChange.fBefore) {
|
||||
if (fromChange.fAtomic && cache->ChangeInfo() == fromChange.fBefore) {
|
||||
cache->RemoveEntry(fromName);
|
||||
if (to == from)
|
||||
cache->AddEntry(toName, fileID, true);
|
||||
cache->SetChangeInfo(fromChange.fAfter);
|
||||
} else if (cache->ChangeInfo() != fromChange.fBefore)
|
||||
} else
|
||||
cache->Trash();
|
||||
}
|
||||
cache->Unlock();
|
||||
|
||||
if (id != NULL)
|
||||
*id = FileIdToInoT(fileID);
|
||||
|
||||
cache = attribute ? to->fAttrCache : to->fCache;
|
||||
cache->Lock();
|
||||
if (cache->Valid()) {
|
||||
if (toChange.fAtomic
|
||||
&& cache->ChangeInfo() == toChange.fBefore) {
|
||||
cache->AddEntry(toName, fileID, true);
|
||||
cache->SetChangeInfo(toChange.fAfter);
|
||||
} else if (to->fCache->ChangeInfo() != toChange.fBefore)
|
||||
cache->Trash();
|
||||
if (to != from) {
|
||||
cache = attribute ? to->fAttrCache : to->fCache;
|
||||
cache->Lock();
|
||||
if (cache->Valid()) {
|
||||
if (toChange.fAtomic
|
||||
&& (cache->ChangeInfo() == toChange.fBefore)) {
|
||||
cache->AddEntry(toName, fileID, true);
|
||||
cache->SetChangeInfo(toChange.fAfter);
|
||||
} else
|
||||
cache->Trash();
|
||||
}
|
||||
cache->Unlock();
|
||||
}
|
||||
cache->Unlock();
|
||||
|
||||
if (attribute) {
|
||||
notify_attribute_changed(from->fFileSystem->DevId(), from->ID(),
|
||||
|
@ -62,7 +62,8 @@ public:
|
||||
ino_t* id = NULL);
|
||||
static status_t Rename(Inode* from, Inode* to,
|
||||
const char* fromName, const char* toName,
|
||||
bool attribute = false, ino_t* id = NULL);
|
||||
bool attribute = false, ino_t* id = NULL,
|
||||
ino_t* oldID = NULL);
|
||||
|
||||
status_t Stat(struct stat* st,
|
||||
OpenAttrCookie* attr = NULL);
|
||||
|
@ -119,9 +119,6 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID,
|
||||
FileHandle* handle, bool parent)
|
||||
{
|
||||
ASSERT(name != NULL);
|
||||
ASSERT(change != NULL);
|
||||
ASSERT(fileID != NULL);
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
@ -143,7 +140,8 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID,
|
||||
else
|
||||
req.LookUp(name);
|
||||
|
||||
req.GetFH();
|
||||
if (handle != NULL)
|
||||
req.GetFH();
|
||||
|
||||
Attribute attr[] = { FATTR4_FSID, FATTR4_FILEID };
|
||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||
@ -177,7 +175,8 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID,
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
reply.GetFH(handle);
|
||||
if (handle != NULL)
|
||||
reply.GetFH(handle);
|
||||
|
||||
result = reply.GetAttr(&values, &count);
|
||||
if (result != B_OK)
|
||||
|
@ -604,7 +604,8 @@ nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name)
|
||||
|
||||
result = acquire_vnode(volume, id);
|
||||
if (result == B_OK) {
|
||||
ASSERT(get_vnode(volume, id, reinterpret_cast<void**>(&vti)) == B_OK);
|
||||
result = get_vnode(volume, id, reinterpret_cast<void**>(&vti));
|
||||
ASSERT(result == B_OK);
|
||||
vti->Remove();
|
||||
put_vnode(volume, id);
|
||||
remove_vnode(volume, id);
|
||||
@ -639,12 +640,27 @@ nfs4_rename(fs_volume* volume, fs_vnode* fromDir, const char* fromName,
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
ino_t id;
|
||||
ino_t oldID;
|
||||
status_t result = Inode::Rename(fromInode, toInode, fromName, toName, false,
|
||||
&id);
|
||||
&id, &oldID);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
VnodeToInode* vti;
|
||||
|
||||
if (oldID != 0) {
|
||||
// we have overriden an inode
|
||||
result = acquire_vnode(volume, oldID);
|
||||
if (result == B_OK) {
|
||||
result = get_vnode(volume, oldID, reinterpret_cast<void**>(&vti));
|
||||
ASSERT(result == B_OK);
|
||||
vti->Remove();
|
||||
put_vnode(volume, oldID);
|
||||
remove_vnode(volume, oldID);
|
||||
put_vnode(volume, oldID);
|
||||
}
|
||||
}
|
||||
|
||||
result = get_vnode(volume, id, reinterpret_cast<void**>(&vti));
|
||||
if (result == B_OK) {
|
||||
Inode* child = vti->Get();
|
||||
|
Loading…
Reference in New Issue
Block a user