75684894 avatar image
0 Votes"
75684894 asked 75684894 commented

[Bug Report] cfapi: CfUpdatePlaceholder may partially update a placeholder file

Hi, I've encountered a problem while using Cloud Filer API. If I'm trying to update a placeholder from zero to a bigger size with CfUpdatePlaceholder and this function returns 0x80070070 - (There is not enough space on the disk), I end up with partially updated placeholder: its size is unchanged while modification time passed via CF_FS_METADATA is changed to a newer value. The expectations are for the call to be atomic, it should either change a placeholder or leave it untouched.

Why this is bad. Real-world case:
- user A creates an empty file with modification time mtime1
- this empty file gets synced to user B
- user A writes some data to a file and its modification time gets updated to mtime2
- Sync Engine tries to update a placeholder file with new modification time and new size on user B device, but due to a lack of free space this operation fails with 0x80070070
- Next time Sync Engine looks at this file it will consider it as updated by user B back to zero size with mtime2 value (and this could actually happen)

Of course, this problem can be workarounded in many ways, bot non of them looks reliable enough. So far I fetch and remember current placeholder state if operation fails to compare this state before re-trying to resize a placeholder file, but there is a potential race where user B actually updates the file back to zero in-between CfUpdatePlaceholder and "fetch" operations.

Minimal reproducible sample:, kudos to @WebDAV-4685, I took your code as a template to demonstrate my issue, hope you don't mind. My output is:

 Cloud sample test!
 Succesfully called AddFolderToSearchIndexer on "file:///C:\Users\max\AppData\Local\Temp\cf-9D6A.tmp-dir"
 platform version is 19041.1682.800
 CfUpdatePlaceholder (with USN) for the file of size 9999999999999 returned hresult = 80070179 (The file is not in sync with the cloud.), usn = 3599343d0
 CfUpdatePlaceholder for the file of size 9184e729fff returned hresult = 80070070 (There is not enough space on the disk.)
 file mtime after updating placeholder is 1601-01-01 00:00:00.0000001
 file usn after updating placeholder is 3599344c0, prev usn was 3599343d0
 Press any key to continue . . .
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello @fukkei , Could you please show a minimal, reproducible sample without private information?
Is a different CfUpdatePlaceholder UpdateUsn returned? And Can CfUpdatePlaceholder UpdateUsn avoid the real-world case?

0 Votes 0 ·
75684894 avatar image 75684894 XiaopoYang-MSFT ·

Hello @XiaopoYang-MSFT! Thanks for the fast response. I've attached the sample to the original question.
As for UpdateUsn, is this feature working? I've tried to use it long ago with no success and I wasn't able to make it work today as well. Look at line 76:

If UpdateUsn is specified the function always fail with not-in-sync error, I couldn't make it work. If I initialize tempUSN with zero, the output doesn't get updated whether CfUpdatePlaceholder fails or not.

However, the real value gets updated, look at line 7 in my sample output

 file usn after updating placeholder is 3599344c0, prev usn was 3599343d0

I was thinking about my "real-world" case and it seems that I was wrong about having a race between updating a placeholder and fetching its state bcs we always use oplocks while updating placeholders and "actual" state is fetched via the same handle, obtained by CfGetWin32HandleFromProtectedHandle. Which, of course, does not eliminate my concern about placeholder inconsistency after failed CfUpdatePlaceholder operation.

0 Votes 0 ·

It's acceptable for CfUpdatePlaceholder updating the metadata but file size when failed. You can Send feedback to Microsoft with the Feedback Hub app about the concern.

1 Vote 1 ·
Show more comments

0 Answers