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

wip: Dokan file lock/unlock #6

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions src/dokan/ceph_dokan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,122 @@ static NTSTATUS WinCephUnmount(
return 0;
}

static NTSTATUS WinCephLockFile(
LPCWSTR FileName,
LONGLONG ByteOffset,
LONGLONG Length,
PDOKAN_FILE_INFO DokanFileInfo) {
if (!Length) {
return 0;
}

std::string path = get_path(FileName);

if (ByteOffset < 0) {
dout(2) << __func__ << " " << path
<< ": Invalid offset: " << ByteOffset << dendl;
return STATUS_INVALID_PARAMETER;
}
if (ByteOffset > CEPH_DOKAN_MAX_FILE_SZ ||
Length > CEPH_DOKAN_MAX_IO_SZ) {
dout(2) << "Lock size exceeds max file length: " << path
<< ". ByteOffset: " << ByteOffset
<< ". Lock length: " << Length << dendl;
return STATUS_FILE_TOO_LARGE;
}

pfd_context fdc = (pfd_context) &(DokanFileInfo->Context);
if (!fdc->fd) {
dout(15) << __func__ << " " << get_path(FileName)
<< ". Missing context, using temporary handle." << dendl;

string path = get_path(FileName);
int fd_new = ceph_open(cmount, path.c_str(), O_RDONLY, 0);
if (fd_new < 0) {
dout(2) << __func__ << " " << path
<< ": ceph_open failed. Error: " << fd_new << dendl;
return cephfs_errno_to_ntstatus_map(fd_new);
}

int ret = ceph_flock(cmount, fd_new, LOCK_EX | LOCK_NB, pthread_self());
if (ret < 0) {
dout(2) << __func__ << " " << path
<< ": ceph_flock lock failed. Error: " << ret
<< ". Path: " << path << dendl;
ceph_close(cmount, fd_new);
return cephfs_errno_to_ntstatus_map(ret);
}
ceph_close(cmount, fd_new);
return 0;
} else {
int ret = ceph_flock(cmount, fdc->fd, LOCK_EX | LOCK_NB, pthread_self());
if (ret < 0) {
dout(2) << __func__ << " " << path
<< ": ceph_flock lock failed. Error: " << ret
<< ". Path: " << path << dendl;
return cephfs_errno_to_ntstatus_map(ret);
}
return 0;
}
}

static NTSTATUS WinCephUnlockFile(
LPCWSTR FileName,
LONGLONG ByteOffset,
LONGLONG Length,
PDOKAN_FILE_INFO DokanFileInfo) {

std::string path = get_path(FileName);

if (ByteOffset < 0) {
dout(2) << __func__ << " " << path
<< ": Invalid offset: " << ByteOffset << dendl;
return STATUS_INVALID_PARAMETER;
}
if (ByteOffset > CEPH_DOKAN_MAX_FILE_SZ ||
Length > CEPH_DOKAN_MAX_IO_SZ) {
dout(2) << "Lock size exceeds max file length: " << path
<< ". ByteOffset: " << ByteOffset
<< ". Lock length: " << Length << dendl;
return STATUS_FILE_TOO_LARGE;
}

pfd_context fdc = (pfd_context) &(DokanFileInfo->Context);
if (!fdc->fd) {
dout(15) << __func__ << " " << get_path(FileName)
<< ". Missing context, using temporary handle." << dendl;

string path = get_path(FileName);
int fd_new = ceph_open(cmount, path.c_str(), O_RDONLY, 0);
if (fd_new < 0) {
dout(2) << __func__ << " " << path
<< ": ceph_open failed. Error: " << fd_new << dendl;
return cephfs_errno_to_ntstatus_map(fd_new);
}

int ret = ceph_flock(cmount, fd_new, LOCK_UN, pthread_self());
if (ret < 0) {
dout(2) << __func__ << " " << path
<< ": ceph_flock unlock failed. Error: " << ret
<< ". Path: " << path << dendl;
ceph_close(cmount, fd_new);
return cephfs_errno_to_ntstatus_map(ret);
}
ceph_close(cmount, fd_new);
return 0;
} else {
int ret = ceph_flock(cmount, fdc->fd, LOCK_UN, pthread_self());

if (ret < 0) {
dout(2) << __func__ << " " << path
<< ": ceph_flock unlock failed. Error: " << ret
<< ". Path: " << path << dendl;
return cephfs_errno_to_ntstatus_map(ret);
}
return 0;
}
}

BOOL WINAPI ConsoleHandler(DWORD dwType)
{
switch(dwType) {
Expand Down Expand Up @@ -926,6 +1042,8 @@ int do_map() {
dokan_operations->GetDiskFreeSpace = WinCephGetDiskFreeSpace;
dokan_operations->GetVolumeInformation = WinCephGetVolumeInformation;
dokan_operations->Unmounted = WinCephUnmount;
dokan_operations->LockFile = WinCephLockFile;
dokan_operations->UnlockFile = WinCephUnlockFile;

ceph_create_with_context(&cmount, g_ceph_context);

Expand Down
1 change: 1 addition & 0 deletions src/dokan/ceph_dokan.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct Config {
bool current_session_only = false;
bool debug = false;
bool dokan_stderr = false;
bool enable_cephfs_locks = false;

int operation_timeout = CEPH_DOKAN_IO_DEFAULT_TIMEOUT;

Expand Down
5 changes: 5 additions & 0 deletions src/dokan/options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Map options:

--debug enable debug output
--dokan-stderr enable stderr Dokan logging
--enable-cephfs-locks enable cephfs file locks

--read-only read-only mount
-o [ --win-mount-mgr] use the Windows mount manager
Expand Down Expand Up @@ -111,6 +112,8 @@ int parse_args(
cfg->removable = true;
} else if (ceph_argparse_flag(args, i, "--win-mount-mgr", "-o", (char *)NULL)) {
cfg->use_win_mount_mgr = true;
} else if (ceph_argparse_flag(args, i, "--enable-cephfs-locks", (char *)NULL)) {
cfg->enable_cephfs_locks = true;
} else if (ceph_argparse_witharg(args, i, &win_vol_name,
"--win-vol-name", (char *)NULL)) {
cfg->win_vol_name = to_wstring(win_vol_name);
Expand Down Expand Up @@ -221,6 +224,8 @@ int set_dokan_options(Config *cfg, PDOKAN_OPTIONS dokan_options) {
dokan_options->Options |= DOKAN_OPTION_DEBUG;
if (cfg->dokan_stderr)
dokan_options->Options |= DOKAN_OPTION_STDERR;
if (cfg->enable_cephfs_locks)
dokan_options->Options |= DOKAN_OPTION_FILELOCK_USER_MODE;

return 0;
}