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

TierFS enhancements #1008

Merged
merged 7 commits into from
Dec 14, 2020
Merged

TierFS enhancements #1008

merged 7 commits into from
Dec 14, 2020

Conversation

itaiad200
Copy link
Contributor

  1. Add metrics to pyramid.TierFS
  2. Single access to block.Adapter during concurrent reads.
  3. Thread-safe directory creation and deletions.

Copy link
Contributor

@arielshaqed arielshaqed left a comment

Choose a reason for hiding this comment

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

Thanks! Looks really good.

Important points:

  1. No test for concurrent deletes, or for concurrent adds and deletes.
  2. Monitoring should put hits and misses in same metric.

pyramid/directory.go Outdated Show resolved Hide resolved
pyramid/directory.go Show resolved Hide resolved
if err := os.Remove(dir); err != nil {
return err
}
dir = parentDir
Copy link
Contributor

Choose a reason for hiding this comment

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

This loop can continue way up, above the planned location. I think directory needs a concept of a ceilingDir or firstAncestorDir or something.

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 was planning for rooted workspace dir to back me up, but it's indeed flaky. Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Much better, but still fragile! If I can control the inputs to removeFromLocal to include .., then this loop happily steps above it.

E.g., if ceilingDir is /a/b/data and I convince the FS to work with a file named x/../../c/d/e/f, then I can happily destroy many things. Right now this is not severe because we do not allow user-controlled paths into the tiers. But e.g. in the (alternate!) future where we afford users more control over the final location of their files, we might end up with user-controlled paths.

I would be happier if we at least documented that paths are not clean and must never be user-controlled. Or we could resolve to actual paths and work from there. E.g. @nopcoder suggested filepath.Clean to resolve a somewhat similar case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding documentation for now, really can't see how the paths (other than the base directory) will be user-controlled in the future.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool. I don't particularly mind "user-controlled" paths when that user is the owner of lakeFS. I'm worried about "user-controlled" paths when they come from a lakeFS user, who is supposed only to have permissions to act on files inside lakeFS.
Thanks!

pyramid/directory.go Outdated Show resolved Hide resolved
pyramid/file.go Outdated
func (f *File) Sync() error {
return f.fh.Sync()
}

func (f *File) Close() error {
Copy link
Contributor

Choose a reason for hiding this comment

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

This existence of this function makes me doubt that the change at line 10 is safe. Specifically, it makes pyramid.File have a safe conversion to File. So now I can

func logAndClose(f *os.File) {
  log("closing!")
  f.Close()
}

func unsafe(f *pyramid.File) {
  // use f...
  logAndClose(f.File)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, fixed!

pyramid/tier_fs.go Show resolved Hide resolved
pyramid/metrics.go Outdated Show resolved Hide resolved
pyramid/tier_fs_test.go Show resolved Hide resolved
pyramid/tier_fs_test.go Show resolved Hide resolved
@@ -17,7 +23,7 @@ import (

var (
fs FS
adapter block.Adapter
adapter *memAdapter
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 just avoid global state and create its test with its own adapter? As is we cannot run tests in parallel, and we need weird checks on the gets counter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes - fixed.

@itaiad200 itaiad200 requested a review from arielshaqed December 8, 2020 16:54
Copy link
Contributor

@arielshaqed arielshaqed left a comment

Choose a reason for hiding this comment

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

Thanks!

Concurrency testing is still incomplete, it seems hard to synchronize all threads of execution to reach the single decision of allowing just one to complete. Perhaps see how @ozkatz did it in ChanLocker?

pyramid/directory.go Outdated Show resolved Hide resolved
pyramid/directory.go Show resolved Hide resolved
prometheus.HistogramOpts{
Name: "tier_fs_eviction_bytes",
Help: "TierFS evicted object size by bytes",
Buckets: []float64{0.5 * kb, 1 * kb, 16 * kb, 32 * kb, 128 * kb, 512 * kb, 1 * mb, 2 * mb, 4 * mb, 8 * mb, 16 * mb, 64 * mb},
Copy link
Contributor

Choose a reason for hiding this comment

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

^^^^^?

if err := os.Remove(dir); err != nil {
return err
}
dir = parentDir
Copy link
Contributor

Choose a reason for hiding this comment

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

Much better, but still fragile! If I can control the inputs to removeFromLocal to include .., then this loop happily steps above it.

E.g., if ceilingDir is /a/b/data and I convince the FS to work with a file named x/../../c/d/e/f, then I can happily destroy many things. Right now this is not severe because we do not allow user-controlled paths into the tiers. But e.g. in the (alternate!) future where we afford users more control over the final location of their files, we might end up with user-controlled paths.

I would be happier if we at least documented that paths are not clean and must never be user-controlled. Or we could resolve to actual paths and work from there. E.g. @nopcoder suggested filepath.Clean to resolve a somewhat similar case.

pyramid/tier_fs_test.go Show resolved Hide resolved
@codecov-io
Copy link

Codecov Report

Merging #1008 (9074876) into master (ed016a1) will increase coverage by 0.07%.
The diff coverage is 68.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1008      +/-   ##
==========================================
+ Coverage   46.26%   46.33%   +0.07%     
==========================================
  Files         152      153       +1     
  Lines       12318    12342      +24     
==========================================
+ Hits         5699     5719      +20     
- Misses       5895     5898       +3     
- Partials      724      725       +1     
Impacted Files Coverage Δ
pyramid/file.go 81.81% <50.00%> (+5.34%) ⬆️
pyramid/tier_fs.go 61.53% <60.00%> (ø)
pyramid/ro_file.go 66.66% <66.66%> (-4.77%) ⬇️
pyramid/directory.go 78.12% <78.12%> (ø)
pyramid/eviction.go 77.77% <100.00%> (ø)
catalog/mvcc/cataloger_create_repository.go 59.25% <0.00%> (-3.71%) ⬇️
catalog/mvcc/cataloger_create_branch.go 81.53% <0.00%> (-3.08%) ⬇️
catalog/mvcc/cataloger_create_entry.go 100.00% <0.00%> (+5.26%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ed016a1...9074876. Read the comment docs.

Copy link
Contributor

@arielshaqed arielshaqed left a comment

Choose a reason for hiding this comment

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

Great, thanks! Sorry for the delayed approval, I forgot about this one.

if err := os.Remove(dir); err != nil {
return err
}
dir = parentDir
Copy link
Contributor

Choose a reason for hiding this comment

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

Cool. I don't particularly mind "user-controlled" paths when that user is the owner of lakeFS. I'm worried about "user-controlled" paths when they come from a lakeFS user, who is supposed only to have permissions to act on files inside lakeFS.
Thanks!

@itaiad200 itaiad200 merged commit 2a70506 into master Dec 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants