Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File permission transfer #155

Closed
wants to merge 18 commits into from
Closed

File permission transfer #155

wants to merge 18 commits into from

Conversation

dliang36
Copy link
Contributor

Implementation and test for keeping file permission during transfer v0.1

Design decision:

  1. Get permission from the same st_mode that is used to get file size, and store permission in each metadata entry of DirectorySourceQueue, in order to avoid calling stat another time.
  2. Default permission is 512 (01000). When perm in WdtFileInfo is default, library behavior is not changed.

Test:

  1. Encode and decode in Protocol
  2. Print src and dst file permissions to file and compare in E2E

TODO:

  1. Shall we consider dir permission?
  2. What if blockDetails.allocationStatus == TO_BE_DELETED but receiver's file permission is owner only?
  3. What if sender side allows only owner's read?
  4. permission changed – only chmod the file. Don’t trans again

@facebook-github-bot
Copy link
Contributor

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at cla@fb.com. Thanks!

If you are contributing on behalf of someone else (eg your employer): the individual CLA is not sufficient - use https://developers.facebook.com/opensource/cla?type=company instead. Contact cla@fb.com if you have any questions.

@facebook-github-bot
Copy link
Contributor

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes

Copy link
Contributor

@uddipta uddipta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dliang36 Awesome work!
Some minor changes needed. Other than those, things look fine.

ByteSource.h Outdated
@@ -44,6 +44,8 @@ struct SourceMetaData {
FileAllocationStatus allocationStatus{NOT_EXISTS};
/// if there is a size mismatch, this is the previous sequence id
int64_t prevSeqId{0};
/// file permission.
int64_t permission{512};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be int32_t.

Protocol.cpp Outdated
@@ -33,6 +33,7 @@ const int Protocol::INCREMENTAL_TAG_VERIFICATION_VERSION = 25;
const int Protocol::DELETE_CMD_VERSION = 26;
const int Protocol::VARINT_CHANGE = 27;
const int Protocol::HEART_BEAT_VERSION = 29;
const int Protocol::KEEP_PERMISSION = 30;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PRESERVE_PERMISSION

Protocol.h Outdated
@@ -218,6 +218,8 @@ struct BlockDetails {
FileAllocationStatus allocationStatus{NOT_EXISTS};
/// seq-id of previous transfer, only valid if there is a size mismatch
int64_t prevSeqId{0};
/// file permission in decimal.
int64_t permission{512};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int32_t

CMakeLists.txt Outdated
@@ -22,7 +22,7 @@ cmake_minimum_required(VERSION 3.2)
# There is no C per se in WDT but if you use CXX only here many checks fail
# Version is Major.Minor.YYMMDDX for up to 10 releases per day (X from 0 to 9)
# Minor currently is also the protocol version - has to match with Protocol.cpp
project("WDT" LANGUAGES C CXX VERSION 1.29.1703251)
project("WDT" LANGUAGES C CXX VERSION 1.30.1703270)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will probably have to change the version to 31, as I am using 30 for an encryption fix.

@@ -35,6 +35,12 @@ struct WdtFileInfo {
/// Whether read should be done using o_direct. If fd is set, this flag will
/// be set automatically to match the fd open mode
bool directReads{false};
/// File permission in decimal. When smaller than oct777 (dec512), the
/// permission will be passed during transfer.
int64_t permission{512};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this check against 512? Can't the default value be 0 and wdt always populates it to the right value in DirectorySourceQueue?

@@ -360,7 +366,9 @@ bool DirectorySourceQueue::explore() {
!std::regex_match(newRelativePath, includeRegex)) {
continue;
}
WdtFileInfo fileInfo(newRelativePath, fileStat.st_size, directReads_);
int perm = fileStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need this logic also in enqueueFiles() method. If the users provide a list of files, we use that method to populate the queue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my previous understanding was: we allow the user to specify a permission, which will be used during createFile. If no valid permission is specified in the request, we will create a 644. (That's why my default permission value is 512. Cuz 0 is still a theoretically valid permission) But I think you are right. It is better to always read the permission from the given file.

@@ -197,7 +198,16 @@ int FileCreator::openExistingFile(ThreadCtx &threadCtx,
return res;
}

int FileCreator::createFile(ThreadCtx &threadCtx, const string &relPathStr) {
int openWithPerm(const char *path, int oFlags, int perm) {
if (perm >= 512) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure we need this check against 512. Just set the default value of BlockDetails::permission to 0644.

@uddipta
Copy link
Contributor

uddipta commented Mar 27, 2017

Regarding your questions, all of them are valid. But, let's try to resolve those one by one in separate diffs.

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes

Copy link
Contributor

@uddipta uddipta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there :)

Protocol.cpp Outdated
@@ -179,6 +183,11 @@ bool Protocol::decodeHeader(int receiverProtocolVersion, char *src,
decodeInt64C(br, blockDetails.dataSize) &&
decodeInt64C(br, blockDetails.offset) &&
decodeInt64C(br, blockDetails.fileSize);
if (ok && receiverProtocolVersion >= PRESERVE_PERMISSION) {
int64_t perm;
ok = decodeInt64C(br, perm);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use decodeInt32

Protocol.h Outdated
/// variants(seq-id, data-size, offset, file-size), 1 byte for flag, 10 bytes
/// prev seq-id
static constexpr int64_t kMaxHeader = 1 + 2 + PATH_MAX + 4 * 10 + 1 + 10;
/// variants(seq-id, data-size, offset, file-size), 2 byte for permission, 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why just 2 byte? Add 10 just to be safe.

@@ -360,7 +366,9 @@ bool DirectorySourceQueue::explore() {
!std::regex_match(newRelativePath, includeRegex)) {
continue;
}
WdtFileInfo fileInfo(newRelativePath, fileStat.st_size, directReads_);
int perm = fileStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: const int perm

info.fileSize = fileStat.st_size;
}
info.permission = fileStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a helper function for getting the permission from the mode? Don't like that we have two places with this constants.

int getPermission(int mode) {
return mode & (S_IRWXU | S_IRWXG | S_IRWXO);
}

@@ -108,7 +108,8 @@ class FileCreator {
*
* @return file descriptor or -1 on error
*/
int createFile(ThreadCtx &threadCtx, const std::string &relPath);
int createFile(ThreadCtx &threadCtx,
const std::string &relPath, int64_t permission);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int32_t permission

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes

@facebook-github-bot
Copy link
Contributor

@uddipta has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@@ -137,7 +137,13 @@ if [ $DO_VERIFY -eq 1 ] ; then
echo "Should be no diff"
(cd $DIR; diff -u src.md5s dst.md5s)
STATUS=$?
if [ $STATUS -eq 0 ] ; then
(cd $DIR/src ; ( find . -type f -printf %f%m\\n | sort ) > ../src.perm )
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find . -type f -printf %f%m\\n doesn't work on Mac. Can you also test files with permissions other than 644?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently within the /tmp/wdtTest_[usrname], there are several files with 664, which include ".a" and ".b" if I remember correctly. Regarding Mac... I am not sure whether we need to consider that. @uddipta Could you clarify this? Similarly I think stat() might not work on Windows.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. we do support Mac. We run open source continuous builds here https://travis-ci.org/facebook/wdt
  2. In e2e simple test, I don't see any files having permissions other than 644.

So, we need to add a file with different permission for testing.

As Jason mentioned before, current find cmd does not work on mac. So, we can disable the test for now on Mac. You can do that using an environment variable. We can have an environment variable like SKIP_PERMISSION_TEST and set it in https://github.com/facebook/wdt/blob/master/build/travis_osx.sh.

If you have access to a mac, you can also try to make the test work for mac. Right now, find is failing for mac, but we are not checking the return code. Both, src.perm and dst.perm are empty, so the test is passing.

Also, run clangformat.sh once.

Every time you update this PR, you should see a travis build/test triggered.

Copy link
Contributor Author

@dliang36 dliang36 Apr 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. OK. I will add a environment var for that. Sorry but I do not have a mac at hand...

  2. Well... there are on my laptop...
    If I just change this line https://github.com/facebook/wdt/pull/155/files#diff-a77a3101b61bf7da9963a0791dba5bb6R247 to return 0644,
    The following tests FAILED:
    10 - FileReaderTests (Failed)
    12 - WdtBasicE2E (Failed)
    19 - WdtSimpleOdirectTest (Failed)
    For 12 & 19, we have things like this:
    Should be no diff
    --- src.perm 2017-04-05 14:56:37.893425997 -0700
    +++ dst.perm 2017-04-05 14:56:37.893425997 -0700
    @@ -1,7 +1,7 @@
    -a664
    -c664
    -file1664
    -file1664
    +a644
    +c644
    +file1644
    +file1644

(Part of "ls -l" output on the src dir is here.)
screenshot from 2017-04-05 15-05-34
Or...is this my OS specific again?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to chmod a file to have permission like 777. Just do that for file1.

Regarding adding test for mac, we will add it later.

Protocol.h Outdated
/// 1 byte for cmd, 2 bytes for file-name length, Max size of filename, 5
/// variants(seq-id, data-size, offset, file-size, permission), 1 byte for
/// flag, 10 bytes prev seq-id
static constexpr int64_t kMaxHeader = 1 + 2 + PATH_MAX + 5 * 10 + 2 + 1 + 10;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No comments for the extra + 2. Where does the 2 extra bytes come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My neglect. I used that for permission before this commit. Should have been deleted. Thank you for pointing out.

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@uddipta has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Contributor

@uddipta uddipta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are several more header files which need to be moved to the beginning of the cpp file.
We should be able to get this diff in after that.

ErrorCodes.cpp Outdated
#include <folly/Conv.h>
#include <string.h>
#include <wdt/ErrorCodes.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert this change?

#include <folly/Bits.h>
#include <folly/Checksum.h>
#include <folly/Conv.h>
#include <folly/Memory.h>
#include <folly/ScopeGuard.h>
#include <folly/String.h>
#include <wdt/ReceiverThread.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert this one too.

"The associated header file of .cpp files should be included before any other includes. (This helps catch missing header file dependencies in the .h)"

This is the lint error I'm seeing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah... this is what clang gave me... Let me revert it...

Reporting.cpp Outdated
#include <folly/String.h>
#include <wdt/Protocol.h>
#include <wdt/Reporting.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one too

SenderThread.cpp Outdated
#include <folly/Bits.h>
#include <folly/Checksum.h>
#include <folly/Conv.h>
#include <folly/Memory.h>
#include <folly/String.h>
#include <sys/stat.h>
#include <wdt/Sender.h>
#include <wdt/SenderThread.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another one

Throttler.cpp Outdated
#include <wdt/ErrorCodes.h>
#include <wdt/Throttler.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one too

WdtOptions.cpp Outdated
#include <glog/logging.h>
#include <wdt/WdtOptions.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another

#include <folly/Conv.h>
#include <folly/Range.h>
#include <wdt/WdtTransferRequest.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one too

# to 0 : when "find -printf %m" does not work, i.e. on Mac
if [ -z "$WDT_TEST_PERMISSION" ] ; then
WDT_TEST_PERMISSION=1
umask 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to set this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you are asking about why umask? Some machines (including mine) have a mask by default, which prevents giving write permission to Others. If we do not umask it, the file created on the receiver side will not have the write perm even if it is a 0777 on the writer side.

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@dliang36 updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@uddipta has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants