From 863784f99178a7870e9d64a84437ad68ca5c7e78 Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Fri, 21 Jul 2017 17:49:30 -0700 Subject: [PATCH] snapshot: replace "readonly" with View snapshot type What started out as a simple PR to remove the "Readonly" column became an adventure to add a proper type for a "View" snapshot. The short story here is that we now get the following output: ``` $ sudo ctr snapshot ls ID PARENT KIND sha256:08c2295a7fa5c220b0f60c994362d290429ad92f6e0235509db91582809442f3 Committed testing4 sha256:08c2295a7fa5c220b0f60c994362d290429ad92f6e0235509db91582809442f3 Active ``` In pursuing this output, it was found that the idea of having "readonly" as an attribute on all snapshots was redundant. For committed, they are always readonly, as they are not accessible without an active snapshot. For active snapshots that were views, we'd have to check the type before interpreting "readonly". With this PR, this is baked fully into the kind of snapshot. When `Snapshotter.View` is called, the kind of snapshot is `KindView`, and the storage system reflects this end to end. Unfortunately, this will break existing users. There is no migration, so they will have to wipe `/var/lib/containerd` and recreate everything. However, this is deemed worthwhile at this point, as we won't have to judge validity of the "Readonly" field when new snapshot types are added. Signed-off-by: Stephen J Day --- api/services/snapshot/v1/snapshots.pb.go | 156 ++++++++------------ api/services/snapshot/v1/snapshots.proto | 8 +- cmd/ctr/snapshot.go | 18 +-- services/snapshot/client.go | 7 +- services/snapshot/service.go | 7 +- snapshot/btrfs/btrfs.go | 47 +++--- snapshot/naive/naive.go | 36 ++--- snapshot/overlay/overlay.go | 43 +++--- snapshot/overlay/overlay_test.go | 12 +- snapshot/snapshotter.go | 23 ++- snapshot/storage/bolt.go | 138 ++++++++---------- snapshot/storage/bolt_test.go | 17 +++ snapshot/storage/metastore.go | 16 +- snapshot/storage/metastore_bench_test.go | 16 +- snapshot/storage/metastore_test.go | 177 +++++++++++------------ snapshot/storage/proto/record.pb.go | 108 +++++--------- snapshot/storage/proto/record.proto | 11 +- 17 files changed, 396 insertions(+), 444 deletions(-) diff --git a/api/services/snapshot/v1/snapshots.pb.go b/api/services/snapshot/v1/snapshots.pb.go index 5f365ef23..5770792ca 100644 --- a/api/services/snapshot/v1/snapshots.pb.go +++ b/api/services/snapshot/v1/snapshots.pb.go @@ -58,17 +58,23 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type Kind int32 const ( - KindActive Kind = 0 - KindCommitted Kind = 1 + KindUnknown Kind = 0 + KindView Kind = 1 + KindActive Kind = 2 + KindCommitted Kind = 3 ) var Kind_name = map[int32]string{ - 0: "ACTIVE", - 1: "COMMITTED", + 0: "UNKNOWN", + 1: "VIEW", + 2: "ACTIVE", + 3: "COMMITTED", } var Kind_value = map[string]int32{ - "ACTIVE": 0, - "COMMITTED": 1, + "UNKNOWN": 0, + "VIEW": 1, + "ACTIVE": 2, + "COMMITTED": 3, } func (x Kind) String() string { @@ -158,10 +164,9 @@ func (*StatSnapshotRequest) ProtoMessage() {} func (*StatSnapshotRequest) Descriptor() ([]byte, []int) { return fileDescriptorSnapshots, []int{8} } type Info struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Parent string `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` - Kind Kind `protobuf:"varint,3,opt,name=kind,proto3,enum=containerd.services.snapshots.v1.Kind" json:"kind,omitempty"` - Readonly bool `protobuf:"varint,4,opt,name=readonly,proto3" json:"readonly,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Parent string `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` + Kind Kind `protobuf:"varint,3,opt,name=kind,proto3,enum=containerd.services.snapshots.v1.Kind" json:"kind,omitempty"` } func (m *Info) Reset() { *m = Info{} } @@ -880,16 +885,6 @@ func (m *Info) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintSnapshots(dAtA, i, uint64(m.Kind)) } - if m.Readonly { - dAtA[i] = 0x20 - i++ - if m.Readonly { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - } return i, nil } @@ -1204,9 +1199,6 @@ func (m *Info) Size() (n int) { if m.Kind != 0 { n += 1 + sovSnapshots(uint64(m.Kind)) } - if m.Readonly { - n += 2 - } return n } @@ -1386,7 +1378,6 @@ func (this *Info) String() string { `Name:` + fmt.Sprintf("%v", this.Name) + `,`, `Parent:` + fmt.Sprintf("%v", this.Parent) + `,`, `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, - `Readonly:` + fmt.Sprintf("%v", this.Readonly) + `,`, `}`, }, "") return s @@ -2535,26 +2526,6 @@ func (m *Info) Unmarshal(dAtA []byte) error { break } } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Readonly", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSnapshots - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Readonly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipSnapshots(dAtA[iNdEx:]) @@ -3122,52 +3093,53 @@ func init() { } var fileDescriptorSnapshots = []byte{ - // 738 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x5d, 0x4f, 0xd4, 0x4c, - 0x18, 0xdd, 0xd2, 0xbe, 0x0b, 0x3c, 0x7c, 0x84, 0x77, 0x58, 0x60, 0xd3, 0x37, 0xe9, 0xdb, 0xf4, - 0xc2, 0x10, 0x2f, 0x5a, 0xc0, 0x08, 0x28, 0x37, 0xb2, 0x2b, 0x31, 0x2b, 0x12, 0x4d, 0x41, 0x22, - 0xc6, 0xc4, 0x94, 0xed, 0xb0, 0x34, 0xd0, 0x4e, 0xed, 0xcc, 0xae, 0x59, 0x2f, 0x8c, 0xde, 0x19, - 0xfe, 0x03, 0x57, 0xfa, 0x2b, 0xfc, 0x05, 0x5c, 0x7a, 0xe9, 0x95, 0x91, 0xfd, 0x25, 0xa6, 0xd3, - 0xd9, 0x0f, 0xa4, 0x66, 0xcb, 0x82, 0x77, 0xcf, 0x7c, 0x9c, 0xf3, 0x9c, 0x9d, 0xd3, 0x39, 0xb3, - 0x50, 0xa9, 0x79, 0xec, 0xb0, 0xbe, 0x6f, 0x56, 0x89, 0x6f, 0x55, 0x49, 0xc0, 0x1c, 0x2f, 0xc0, - 0x91, 0xdb, 0x5b, 0x3a, 0xa1, 0x67, 0x51, 0x1c, 0x35, 0xbc, 0x2a, 0xa6, 0x16, 0x0d, 0x9c, 0x90, - 0x1e, 0x12, 0x66, 0x35, 0x16, 0x3b, 0x35, 0x35, 0xc3, 0x88, 0x30, 0x82, 0xf4, 0x2e, 0xc8, 0x6c, - 0x03, 0xcc, 0xee, 0xa6, 0xc6, 0xa2, 0x5a, 0xa8, 0x91, 0x1a, 0xe1, 0x9b, 0xad, 0xb8, 0x4a, 0x70, - 0xea, 0x7f, 0x35, 0x42, 0x6a, 0xc7, 0xd8, 0xe2, 0xa3, 0xfd, 0xfa, 0x81, 0x85, 0xfd, 0x90, 0x35, - 0xc5, 0xe2, 0x72, 0x26, 0x7d, 0xac, 0x19, 0x62, 0x6a, 0xf9, 0xa4, 0x1e, 0xb0, 0x04, 0x67, 0xb8, - 0x30, 0xfb, 0x2c, 0xc2, 0xa1, 0x13, 0xe1, 0x6d, 0xa1, 0xc0, 0xc6, 0x6f, 0xea, 0x98, 0x32, 0xa4, - 0xc3, 0x58, 0x5b, 0x14, 0xc3, 0x51, 0x51, 0xd2, 0xa5, 0xf9, 0x51, 0xbb, 0x77, 0x0a, 0x4d, 0x81, - 0x7c, 0x84, 0x9b, 0xc5, 0x21, 0xbe, 0x12, 0x97, 0x68, 0x16, 0xf2, 0x31, 0x55, 0xc0, 0x8a, 0x32, - 0x9f, 0x14, 0x23, 0xe3, 0x31, 0xcc, 0x5d, 0xea, 0x42, 0x43, 0x12, 0x50, 0x8c, 0x2c, 0xc8, 0x73, - 0x3d, 0xb4, 0x28, 0xe9, 0xf2, 0xfc, 0xd8, 0xd2, 0x9c, 0xd9, 0x73, 0x3c, 0x5c, 0xaf, 0xb9, 0x15, - 0xaf, 0xdb, 0x62, 0x9b, 0xe1, 0xc0, 0xf4, 0xae, 0x87, 0xdf, 0xfe, 0x4d, 0xb9, 0x8f, 0xa0, 0x70, - 0xb1, 0xc5, 0xa0, 0x5a, 0xcb, 0x30, 0xc1, 0x27, 0xe8, 0x35, 0x54, 0x1a, 0xeb, 0x30, 0xd9, 0x26, - 0x19, 0x54, 0xc7, 0x26, 0xcc, 0xd8, 0xd8, 0x27, 0x8d, 0x9b, 0x30, 0xd9, 0x78, 0x0d, 0x33, 0x65, - 0xe2, 0xfb, 0x1e, 0xbb, 0x3a, 0x19, 0x02, 0x25, 0x70, 0x7c, 0x2c, 0xd8, 0x78, 0xdd, 0x6e, 0x20, - 0x77, 0x1b, 0x54, 0x60, 0x7a, 0x9b, 0x39, 0xec, 0x26, 0xb4, 0x9e, 0x48, 0xa0, 0x54, 0x82, 0x03, - 0xd2, 0xe9, 0x2c, 0xf5, 0x74, 0xee, 0xda, 0x3f, 0xd4, 0x6b, 0x3f, 0xba, 0x0f, 0xca, 0x91, 0x17, - 0xb8, 0x5c, 0xd2, 0xe4, 0xd2, 0x2d, 0xb3, 0xdf, 0x7d, 0x35, 0x37, 0xbd, 0xc0, 0xb5, 0x39, 0x06, - 0xa9, 0x30, 0x12, 0x61, 0xc7, 0x25, 0xc1, 0x71, 0xb3, 0xa8, 0xe8, 0xd2, 0xfc, 0x88, 0xdd, 0x19, - 0x1b, 0x2f, 0xa0, 0x70, 0xf1, 0x77, 0x09, 0x3b, 0x1f, 0x80, 0xe2, 0x05, 0x07, 0x84, 0x6b, 0x1b, - 0xcb, 0xd2, 0x2f, 0xfe, 0x45, 0x25, 0xe5, 0xec, 0xc7, 0xff, 0x39, 0x9b, 0x23, 0x8d, 0x55, 0x28, - 0x3c, 0xf1, 0x68, 0x87, 0x39, 0xfb, 0xe7, 0x66, 0xec, 0xc1, 0xcc, 0x6f, 0xc8, 0x4b, 0xa2, 0xe4, - 0x01, 0x45, 0x95, 0x60, 0xfc, 0x39, 0x75, 0x6a, 0xf8, 0x3a, 0xfe, 0xad, 0xc1, 0x84, 0xe0, 0x10, - 0xb2, 0x10, 0x28, 0xd4, 0x7b, 0x97, 0xf8, 0x28, 0xdb, 0xbc, 0x8e, 0x7d, 0xf4, 0x02, 0xe2, 0x62, - 0xca, 0x91, 0xb2, 0x2d, 0x46, 0xb7, 0x6d, 0x50, 0x36, 0x13, 0x4f, 0xf2, 0xeb, 0xe5, 0x9d, 0xca, - 0xee, 0xc6, 0x54, 0x4e, 0x9d, 0x3c, 0x39, 0xd5, 0x21, 0x9e, 0x5d, 0xaf, 0x32, 0xaf, 0x81, 0x91, - 0x0e, 0xa3, 0xe5, 0xa7, 0x5b, 0x5b, 0x95, 0x9d, 0x9d, 0x8d, 0x87, 0x53, 0x92, 0xfa, 0xef, 0xc9, - 0xa9, 0x3e, 0x11, 0x2f, 0x27, 0x5f, 0x38, 0xc3, 0xae, 0x3a, 0xfe, 0xe9, 0xb3, 0x96, 0xfb, 0xfa, - 0x45, 0xe3, 0x5c, 0x4b, 0x1f, 0x87, 0x61, 0xb4, 0x73, 0x58, 0xe8, 0x3d, 0x0c, 0x8b, 0x5c, 0x43, - 0xab, 0xfd, 0x4f, 0x28, 0x3d, 0x68, 0xd5, 0x7b, 0x03, 0x20, 0xc5, 0x69, 0xd4, 0x41, 0x89, 0x83, - 0x0a, 0xdd, 0xed, 0x4f, 0x91, 0x92, 0x99, 0xea, 0xf2, 0x55, 0x61, 0xa2, 0xed, 0x11, 0xe4, 0x93, - 0x44, 0x42, 0x56, 0x7f, 0x86, 0x0b, 0x01, 0xa8, 0x2e, 0x64, 0x07, 0x88, 0x66, 0x7b, 0x90, 0x4f, - 0xcc, 0x40, 0x2b, 0xfd, 0xb1, 0xa9, 0xc1, 0xa4, 0xce, 0x9a, 0xc9, 0xd3, 0x69, 0xb6, 0x9f, 0x4e, - 0x73, 0x23, 0x7e, 0x3a, 0x63, 0xea, 0x24, 0x16, 0xb3, 0x50, 0xa7, 0x06, 0xe8, 0x1f, 0xa9, 0xeb, - 0xa0, 0xc4, 0x77, 0x3d, 0x8b, 0x33, 0x29, 0x59, 0x97, 0xc5, 0x99, 0xd4, 0x28, 0x69, 0x82, 0x12, - 0x5f, 0x67, 0x94, 0x01, 0x9f, 0x16, 0x18, 0xea, 0xca, 0x95, 0x71, 0x49, 0xe3, 0x05, 0x09, 0x1d, - 0xc2, 0x3f, 0xfc, 0xaa, 0x22, 0xb3, 0x3f, 0x47, 0x6f, 0x2e, 0xa8, 0x56, 0xe6, 0xfd, 0x49, 0xaf, - 0xd2, 0xab, 0xb3, 0x73, 0x2d, 0xf7, 0xfd, 0x5c, 0xcb, 0x7d, 0x68, 0x69, 0xd2, 0x59, 0x4b, 0x93, - 0xbe, 0xb5, 0x34, 0xe9, 0x67, 0x4b, 0x93, 0x5e, 0x96, 0x06, 0xfe, 0x97, 0xb6, 0xd6, 0xae, 0xf7, - 0xf3, 0xdc, 0xc9, 0x3b, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x62, 0xfd, 0xaf, 0x9e, 0xf2, 0x09, - 0x00, 0x00, + // 766 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x4e, 0xdb, 0x4a, + 0x18, 0x8d, 0xb1, 0x6f, 0xb8, 0x7c, 0x01, 0x6e, 0xee, 0x10, 0x42, 0xe4, 0x7b, 0xe5, 0x6b, 0x79, + 0x71, 0x85, 0xba, 0xb0, 0x81, 0xaa, 0x40, 0xcb, 0xa6, 0x24, 0x8d, 0xaa, 0x94, 0x02, 0x95, 0xf9, + 0x2b, 0x55, 0xa5, 0xca, 0x24, 0x43, 0xb0, 0xd2, 0xcc, 0xa4, 0xf1, 0x24, 0x28, 0x5d, 0x54, 0xed, + 0x0e, 0xe5, 0x1d, 0xb2, 0x6a, 0x9f, 0xa2, 0x4f, 0xc0, 0xb2, 0xcb, 0xae, 0xaa, 0x92, 0x27, 0xa9, + 0x66, 0xec, 0xfc, 0x50, 0x52, 0xc5, 0x04, 0xba, 0xfb, 0x3c, 0xdf, 0x9c, 0xf3, 0x9d, 0xcc, 0xb1, + 0xcf, 0x04, 0x72, 0x45, 0x97, 0x9d, 0xd4, 0x8e, 0xcc, 0x3c, 0x2d, 0x5b, 0x79, 0x4a, 0x98, 0xe3, + 0x12, 0x5c, 0x2d, 0xf4, 0x97, 0x4e, 0xc5, 0xb5, 0x3c, 0x5c, 0xad, 0xbb, 0x79, 0xec, 0x59, 0x1e, + 0x71, 0x2a, 0xde, 0x09, 0x65, 0x56, 0x7d, 0xb1, 0x5b, 0x7b, 0x66, 0xa5, 0x4a, 0x19, 0x45, 0x7a, + 0x0f, 0x64, 0x76, 0x00, 0x66, 0x6f, 0x53, 0x7d, 0x51, 0x4d, 0x14, 0x69, 0x91, 0x8a, 0xcd, 0x16, + 0xaf, 0x7c, 0x9c, 0xfa, 0x4f, 0x91, 0xd2, 0xe2, 0x6b, 0x6c, 0x89, 0xa7, 0xa3, 0xda, 0xb1, 0x85, + 0xcb, 0x15, 0xd6, 0x08, 0x9a, 0xcb, 0xa1, 0xf4, 0xb1, 0x46, 0x05, 0x7b, 0x56, 0x99, 0xd6, 0x08, + 0xf3, 0x71, 0x46, 0x01, 0x92, 0xcf, 0xaa, 0xb8, 0xe2, 0x54, 0xf1, 0x4e, 0xa0, 0xc0, 0xc6, 0x6f, + 0x6a, 0xd8, 0x63, 0x48, 0x87, 0x58, 0x47, 0x14, 0xc3, 0xd5, 0x94, 0xa4, 0x4b, 0xf3, 0x13, 0x76, + 0xff, 0x12, 0x8a, 0x83, 0x5c, 0xc2, 0x8d, 0xd4, 0x98, 0xe8, 0xf0, 0x12, 0x25, 0x21, 0xca, 0xa9, + 0x08, 0x4b, 0xc9, 0x62, 0x31, 0x78, 0x32, 0x9e, 0xc0, 0xdc, 0x95, 0x29, 0x5e, 0x85, 0x12, 0x0f, + 0x23, 0x0b, 0xa2, 0x42, 0x8f, 0x97, 0x92, 0x74, 0x79, 0x3e, 0xb6, 0x34, 0x67, 0xf6, 0x1d, 0x8f, + 0xd0, 0x6b, 0x6e, 0xf2, 0xbe, 0x1d, 0x6c, 0x33, 0x1c, 0x98, 0xd9, 0x77, 0xf1, 0xe9, 0xef, 0x94, + 0xfb, 0x18, 0x12, 0x97, 0x47, 0x8c, 0xaa, 0x35, 0x03, 0x53, 0x62, 0xc1, 0xbb, 0x81, 0x4a, 0x63, + 0x1d, 0xa6, 0x3b, 0x24, 0xa3, 0xea, 0xd8, 0x80, 0x59, 0x1b, 0x97, 0x69, 0xfd, 0x36, 0x4c, 0x36, + 0x5e, 0xc1, 0x6c, 0x86, 0x96, 0xcb, 0x2e, 0xbb, 0x3e, 0x19, 0x02, 0x85, 0x38, 0x65, 0x1c, 0xb0, + 0x89, 0xba, 0x33, 0x40, 0xee, 0x0d, 0xc8, 0xc1, 0xcc, 0x0e, 0x73, 0xd8, 0x6d, 0x68, 0x25, 0xa0, + 0xe4, 0xc8, 0x31, 0xed, 0x0e, 0x96, 0xfa, 0x06, 0xf7, 0xdc, 0x1f, 0xeb, 0x77, 0x1f, 0x3d, 0x00, + 0xa5, 0xe4, 0x92, 0x82, 0x50, 0x34, 0xbd, 0xf4, 0xbf, 0x39, 0xec, 0x73, 0x35, 0x37, 0x5c, 0x52, + 0xb0, 0x05, 0xc6, 0x78, 0x0e, 0x89, 0xcb, 0xd2, 0x03, 0xc7, 0x1e, 0x82, 0xe2, 0x92, 0x63, 0x2a, + 0xe6, 0xc7, 0xc2, 0x70, 0x72, 0xd5, 0x69, 0xe5, 0xfc, 0xdb, 0x7f, 0x11, 0x5b, 0x20, 0x8d, 0x55, + 0x48, 0x3c, 0x75, 0xbd, 0x2e, 0x73, 0xf8, 0x37, 0xca, 0x38, 0x84, 0xd9, 0x9f, 0x90, 0x57, 0x44, + 0xc9, 0x23, 0x8a, 0x4a, 0xc3, 0xe4, 0x9e, 0xe7, 0x14, 0xf1, 0x4d, 0x2c, 0x5a, 0x83, 0xa9, 0x80, + 0x23, 0x90, 0x85, 0x40, 0xf1, 0xdc, 0xb7, 0xbe, 0x57, 0xb2, 0x2d, 0x6a, 0xee, 0x95, 0x4b, 0x68, + 0x01, 0x7b, 0x02, 0x29, 0xdb, 0xc1, 0xd3, 0x9d, 0x33, 0x09, 0x14, 0x7e, 0xfc, 0xe8, 0x5f, 0x18, + 0xdf, 0xdb, 0xda, 0xd8, 0xda, 0x3e, 0xd8, 0x8a, 0x47, 0xd4, 0xbf, 0x9a, 0x2d, 0x3d, 0xc6, 0x97, + 0xf7, 0x48, 0x89, 0xd0, 0x53, 0x82, 0x92, 0xa0, 0xec, 0xe7, 0xb2, 0x07, 0x71, 0x49, 0x9d, 0x6c, + 0xb6, 0xf4, 0x3f, 0x79, 0x8b, 0x7f, 0xe0, 0x48, 0x85, 0xe8, 0x7a, 0x66, 0x37, 0xb7, 0x9f, 0x8d, + 0x8f, 0xa9, 0xd3, 0xcd, 0x96, 0x0e, 0xbc, 0xb3, 0x9e, 0x67, 0x6e, 0x1d, 0x23, 0x1d, 0x26, 0x32, + 0xdb, 0x9b, 0x9b, 0xb9, 0xdd, 0xdd, 0xec, 0xa3, 0xb8, 0xac, 0xfe, 0xdd, 0x6c, 0xe9, 0x53, 0xbc, + 0xed, 0xbf, 0xfb, 0x0c, 0x17, 0xd4, 0xc9, 0xb3, 0x8f, 0x5a, 0xe4, 0xf3, 0x27, 0x4d, 0x28, 0x58, + 0xfa, 0x30, 0x0e, 0x13, 0xdd, 0x33, 0x46, 0xef, 0x60, 0x3c, 0x48, 0x3c, 0xb4, 0x3a, 0xfc, 0x60, + 0x07, 0x47, 0xb0, 0x7a, 0x7f, 0x04, 0x64, 0x70, 0x88, 0x35, 0x50, 0xc4, 0x2f, 0xbc, 0x37, 0x9c, + 0x62, 0x40, 0x9a, 0xaa, 0xcb, 0xd7, 0x85, 0x05, 0x63, 0x4b, 0x10, 0xf5, 0xb3, 0x0a, 0x59, 0xc3, + 0x19, 0x2e, 0x45, 0xa3, 0xba, 0x10, 0x1e, 0x10, 0x0c, 0x3b, 0x84, 0xa8, 0x6f, 0x06, 0x5a, 0x19, + 0x8e, 0x1d, 0x18, 0x59, 0x6a, 0xd2, 0xf4, 0x2f, 0x55, 0xb3, 0x73, 0xa9, 0x9a, 0x59, 0x7e, 0xa9, + 0x72, 0x6a, 0x3f, 0x30, 0xc3, 0x50, 0x0f, 0x8c, 0xd6, 0x5f, 0x52, 0xd7, 0x40, 0xe1, 0x11, 0x11, + 0xc6, 0x99, 0x01, 0x29, 0x18, 0xc6, 0x99, 0x81, 0x09, 0xd4, 0x00, 0x85, 0xa7, 0x00, 0x0a, 0x81, + 0x1f, 0x94, 0x33, 0xea, 0xca, 0xb5, 0x71, 0xfe, 0xe0, 0x05, 0x09, 0x9d, 0xc0, 0x1f, 0xe2, 0x0b, + 0x47, 0xe6, 0x70, 0x8e, 0xfe, 0x38, 0x51, 0xad, 0xd0, 0xfb, 0xfd, 0x59, 0xe9, 0x97, 0xe7, 0x17, + 0x5a, 0xe4, 0xeb, 0x85, 0x16, 0x79, 0xdf, 0xd6, 0xa4, 0xf3, 0xb6, 0x26, 0x7d, 0x69, 0x6b, 0xd2, + 0xf7, 0xb6, 0x26, 0xbd, 0x48, 0x8f, 0xfc, 0xff, 0x6d, 0xad, 0x53, 0x1f, 0x45, 0x85, 0x93, 0x77, + 0x7f, 0x04, 0x00, 0x00, 0xff, 0xff, 0x51, 0x4b, 0x27, 0x3b, 0x0c, 0x0a, 0x00, 0x00, } diff --git a/api/services/snapshot/v1/snapshots.proto b/api/services/snapshot/v1/snapshots.proto index db67ae4ba..3f5180dc1 100644 --- a/api/services/snapshot/v1/snapshots.proto +++ b/api/services/snapshot/v1/snapshots.proto @@ -69,16 +69,16 @@ enum Kind { option (gogoproto.goproto_enum_prefix) = false; option (gogoproto.enum_customname) = "Kind"; - ACTIVE = 0 [(gogoproto.enumvalue_customname) = "KindActive"]; - - COMMITTED = 1 [(gogoproto.enumvalue_customname) = "KindCommitted"]; + UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "KindUnknown"]; + VIEW = 1 [(gogoproto.enumvalue_customname) = "KindView"]; + ACTIVE = 2 [(gogoproto.enumvalue_customname) = "KindActive"]; + COMMITTED = 3 [(gogoproto.enumvalue_customname) = "KindCommitted"]; } message Info { string name = 1; string parent = 2; Kind kind = 3; - bool readonly = 4; } message StatSnapshotResponse { diff --git a/cmd/ctr/snapshot.go b/cmd/ctr/snapshot.go index c7a7a6b73..bed155cdb 100644 --- a/cmd/ctr/snapshot.go +++ b/cmd/ctr/snapshot.go @@ -89,10 +89,13 @@ var listSnapshotCommand = cli.Command{ } tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0) - fmt.Fprintln(tw, "ID\tParent\tState\tReadonly\t") + fmt.Fprintln(tw, "ID\tPARENT\tKIND\t") if err := snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error { - fmt.Fprintf(tw, "%v\t%v\t%v\t%t\t\n", info.Name, info.Parent, state(info.Kind), info.Readonly) + fmt.Fprintf(tw, "%v\t%v\t%v\t\n", + info.Name, + info.Parent, + info.Kind) return nil }); err != nil { return err @@ -102,17 +105,6 @@ var listSnapshotCommand = cli.Command{ }, } -func state(k snapshot.Kind) string { - switch k { - case snapshot.KindActive: - return "active" - case snapshot.KindCommitted: - return "committed" - default: - return "" - } -} - var usageSnapshotCommand = cli.Command{ Name: "usage", Usage: "Usage snapshots", diff --git a/services/snapshot/client.go b/services/snapshot/client.go index 1ff94a3df..c5b4ab53b 100644 --- a/services/snapshot/client.go +++ b/services/snapshot/client.go @@ -135,10 +135,9 @@ func toKind(kind snapshotapi.Kind) snapshot.Kind { func toInfo(info snapshotapi.Info) snapshot.Info { return snapshot.Info{ - Name: info.Name, - Parent: info.Parent, - Kind: toKind(info.Kind), - Readonly: info.Readonly, + Name: info.Name, + Parent: info.Parent, + Kind: toKind(info.Kind), } } diff --git a/services/snapshot/service.go b/services/snapshot/service.go index 089812e09..3972f0f0d 100644 --- a/services/snapshot/service.go +++ b/services/snapshot/service.go @@ -269,10 +269,9 @@ func fromKind(kind snapshot.Kind) snapshotapi.Kind { func fromInfo(info snapshot.Info) snapshotapi.Info { return snapshotapi.Info{ - Name: info.Name, - Parent: info.Parent, - Kind: fromKind(info.Kind), - Readonly: info.Readonly, + Name: info.Name, + Parent: info.Parent, + Kind: fromKind(info.Kind), } } diff --git a/snapshot/btrfs/btrfs.go b/snapshot/btrfs/btrfs.go index cec28f02e..e9f963b07 100644 --- a/snapshot/btrfs/btrfs.go +++ b/snapshot/btrfs/btrfs.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "github.com/containerd/btrfs" "github.com/containerd/containerd/log" @@ -58,11 +59,13 @@ func NewSnapshotter(root string) (snapshot.Snapshotter, error) { } var ( active = filepath.Join(root, "active") + view = filepath.Join(root, "view") snapshots = filepath.Join(root, "snapshots") ) for _, path := range []string{ active, + view, snapshots, } { if err := os.Mkdir(path, 0755); err != nil && !os.IsExist(err) { @@ -127,14 +130,14 @@ func (b *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho } func (b *snapshotter) Prepare(ctx context.Context, key, parent string) ([]mount.Mount, error) { - return b.makeActive(ctx, key, parent, false) + return b.makeSnapshot(ctx, snapshot.KindActive, key, parent) } func (b *snapshotter) View(ctx context.Context, key, parent string) ([]mount.Mount, error) { - return b.makeActive(ctx, key, parent, true) + return b.makeSnapshot(ctx, snapshot.KindView, key, parent) } -func (b *snapshotter) makeActive(ctx context.Context, key, parent string, readonly bool) ([]mount.Mount, error) { +func (b *snapshotter) makeSnapshot(ctx context.Context, kind snapshot.Kind, key, parent string) ([]mount.Mount, error) { ctx, t, err := b.ms.TransactionContext(ctx, true) if err != nil { return nil, err @@ -147,23 +150,29 @@ func (b *snapshotter) makeActive(ctx context.Context, key, parent string, readon } }() - a, err := storage.CreateActive(ctx, key, parent, readonly) + s, err := storage.CreateSnapshot(ctx, kind, key, parent) if err != nil { return nil, err } - target := filepath.Join(b.root, "active", a.ID) + target := filepath.Join(b.root, strings.ToLower(s.Kind.String()), s.ID) - if len(a.ParentIDs) == 0 { + if len(s.ParentIDs) == 0 { // create new subvolume // btrfs subvolume create /dir if err = btrfs.SubvolCreate(target); err != nil { return nil, err } } else { - parentp := filepath.Join(b.root, "snapshots", a.ParentIDs[0]) + parentp := filepath.Join(b.root, "snapshots", s.ParentIDs[0]) + + var readonly bool + if kind == snapshot.KindView { + readonly = true + } + // btrfs subvolume snapshot /parent /subvol - if err = btrfs.SubvolSnapshot(target, parentp, a.Readonly); err != nil { + if err = btrfs.SubvolSnapshot(target, parentp, readonly); err != nil { return nil, err } } @@ -256,12 +265,13 @@ func (b *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, er if err != nil { return nil, err } - a, err := storage.GetActive(ctx, key) + s, err := storage.GetSnapshot(ctx, key) t.Rollback() if err != nil { return nil, errors.Wrap(err, "failed to get active snapshot") } - dir := filepath.Join(b.root, "active", a.ID) + + dir := filepath.Join(b.root, strings.ToLower(s.Kind.String()), s.ID) return b.mounts(dir) } @@ -296,18 +306,15 @@ func (b *snapshotter) Remove(ctx context.Context, key string) (err error) { return errors.Wrap(err, "failed to remove snapshot") } - if k == snapshot.KindActive { + switch k { + case snapshot.KindView: + source = filepath.Join(b.root, "view", id) + removed = filepath.Join(b.root, "view", "rm-"+id) + readonly = true + case snapshot.KindActive: source = filepath.Join(b.root, "active", id) - - info, err := btrfs.SubvolInfo(source) - if err != nil { - source = "" - return err - } - - readonly = info.Readonly removed = filepath.Join(b.root, "active", "rm-"+id) - } else { + case snapshot.KindCommitted: source = filepath.Join(b.root, "snapshots", id) removed = filepath.Join(b.root, "snapshots", "rm-"+id) readonly = true diff --git a/snapshot/naive/naive.go b/snapshot/naive/naive.go index 88fc5539b..a78a76145 100644 --- a/snapshot/naive/naive.go +++ b/snapshot/naive/naive.go @@ -94,11 +94,11 @@ func (o *snapshotter) Usage(ctx context.Context, key string) (snapshot.Usage, er } func (o *snapshotter) Prepare(ctx context.Context, key, parent string) ([]mount.Mount, error) { - return o.createActive(ctx, key, parent, false) + return o.createSnapshot(ctx, snapshot.KindActive, key, parent) } func (o *snapshotter) View(ctx context.Context, key, parent string) ([]mount.Mount, error) { - return o.createActive(ctx, key, parent, true) + return o.createSnapshot(ctx, snapshot.KindView, key, parent) } // Mounts returns the mounts for the transaction identified by key. Can be @@ -110,12 +110,12 @@ func (o *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, er if err != nil { return nil, err } - active, err := storage.GetActive(ctx, key) + s, err := storage.GetSnapshot(ctx, key) t.Rollback() if err != nil { - return nil, errors.Wrap(err, "failed to get active mount") + return nil, errors.Wrap(err, "failed to get snapshot mount") } - return o.mounts(active), nil + return o.mounts(s), nil } func (o *snapshotter) Commit(ctx context.Context, name, key string) error { @@ -203,13 +203,13 @@ func (o *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho return storage.WalkInfo(ctx, fn) } -func (o *snapshotter) createActive(ctx context.Context, key, parent string, readonly bool) ([]mount.Mount, error) { +func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshot.Kind, key, parent string) ([]mount.Mount, error) { var ( err error path, td string ) - if !readonly || parent == "" { + if kind == snapshot.KindActive || parent == "" { td, err = ioutil.TempDir(filepath.Join(o.root, "snapshots"), "new-") if err != nil { return nil, errors.Wrap(err, "failed to create temp dir") @@ -235,23 +235,23 @@ func (o *snapshotter) createActive(ctx context.Context, key, parent string, read return nil, err } - active, err := storage.CreateActive(ctx, key, parent, readonly) + s, err := storage.CreateSnapshot(ctx, kind, key, parent) if err != nil { if rerr := t.Rollback(); rerr != nil { log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") } - return nil, errors.Wrap(err, "failed to create active") + return nil, errors.Wrap(err, "failed to create snapshot") } if td != "" { - if len(active.ParentIDs) > 0 { - parent := o.getSnapshotDir(active.ParentIDs[0]) + if len(s.ParentIDs) > 0 { + parent := o.getSnapshotDir(s.ParentIDs[0]) if err := fs.CopyDir(td, parent); err != nil { return nil, errors.Wrap(err, "copying of parent failed") } } - path = o.getSnapshotDir(active.ID) + path = o.getSnapshotDir(s.ID) if err := os.Rename(td, path); err != nil { if rerr := t.Rollback(); rerr != nil { log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") @@ -265,29 +265,29 @@ func (o *snapshotter) createActive(ctx context.Context, key, parent string, read return nil, errors.Wrap(err, "commit failed") } - return o.mounts(active), nil + return o.mounts(s), nil } func (o *snapshotter) getSnapshotDir(id string) string { return filepath.Join(o.root, "snapshots", id) } -func (o *snapshotter) mounts(active storage.Active) []mount.Mount { +func (o *snapshotter) mounts(s storage.Snapshot) []mount.Mount { var ( roFlag string source string ) - if active.Readonly { + if s.Kind == snapshot.KindView { roFlag = "ro" } else { roFlag = "rw" } - if len(active.ParentIDs) == 0 || !active.Readonly { - source = o.getSnapshotDir(active.ID) + if len(s.ParentIDs) == 0 || s.Kind == snapshot.KindActive { + source = o.getSnapshotDir(s.ID) } else { - source = o.getSnapshotDir(active.ParentIDs[0]) + source = o.getSnapshotDir(s.ParentIDs[0]) } return []mount.Mount{ diff --git a/snapshot/overlay/overlay.go b/snapshot/overlay/overlay.go index a8775fa56..c759829d5 100644 --- a/snapshot/overlay/overlay.go +++ b/snapshot/overlay/overlay.go @@ -122,11 +122,11 @@ func (o *snapshotter) Usage(ctx context.Context, key string) (snapshot.Usage, er } func (o *snapshotter) Prepare(ctx context.Context, key, parent string) ([]mount.Mount, error) { - return o.createActive(ctx, key, parent, false) + return o.createSnapshot(ctx, snapshot.KindActive, key, parent) } func (o *snapshotter) View(ctx context.Context, key, parent string) ([]mount.Mount, error) { - return o.createActive(ctx, key, parent, true) + return o.createSnapshot(ctx, snapshot.KindView, key, parent) } // Mounts returns the mounts for the transaction identified by key. Can be @@ -138,12 +138,12 @@ func (o *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, er if err != nil { return nil, err } - active, err := storage.GetActive(ctx, key) + s, err := storage.GetSnapshot(ctx, key) t.Rollback() if err != nil { return nil, errors.Wrap(err, "failed to get active mount") } - return o.mounts(active), nil + return o.mounts(s), nil } func (o *snapshotter) Commit(ctx context.Context, name, key string) error { @@ -230,7 +230,7 @@ func (o *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho return storage.WalkInfo(ctx, fn) } -func (o *snapshotter) createActive(ctx context.Context, key, parent string, readonly bool) ([]mount.Mount, error) { +func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshot.Kind, key, parent string) ([]mount.Mount, error) { var ( path string snapshotDir = filepath.Join(o.root, "snapshots") @@ -258,7 +258,8 @@ func (o *snapshotter) createActive(ctx context.Context, key, parent string, read if err = os.MkdirAll(filepath.Join(td, "fs"), 0711); err != nil { return nil, err } - if !readonly { + + if kind == snapshot.KindActive { if err = os.MkdirAll(filepath.Join(td, "work"), 0700); err != nil { return nil, err } @@ -269,7 +270,7 @@ func (o *snapshotter) createActive(ctx context.Context, key, parent string, read return nil, err } - active, err := storage.CreateActive(ctx, key, parent, readonly) + s, err := storage.CreateSnapshot(ctx, kind, key, parent) if err != nil { if rerr := t.Rollback(); rerr != nil { log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") @@ -277,7 +278,7 @@ func (o *snapshotter) createActive(ctx context.Context, key, parent string, read return nil, errors.Wrap(err, "failed to create active") } - path = filepath.Join(snapshotDir, active.ID) + path = filepath.Join(snapshotDir, s.ID) if err = os.Rename(td, path); err != nil { if rerr := t.Rollback(); rerr != nil { log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") @@ -290,21 +291,21 @@ func (o *snapshotter) createActive(ctx context.Context, key, parent string, read return nil, errors.Wrap(err, "commit failed") } - return o.mounts(active), nil + return o.mounts(s), nil } -func (o *snapshotter) mounts(active storage.Active) []mount.Mount { - if len(active.ParentIDs) == 0 { +func (o *snapshotter) mounts(s storage.Snapshot) []mount.Mount { + if len(s.ParentIDs) == 0 { // if we only have one layer/no parents then just return a bind mount as overlay // will not work roFlag := "rw" - if active.Readonly { + if s.Kind == snapshot.KindView { roFlag = "ro" } return []mount.Mount{ { - Source: o.upperPath(active.ID), + Source: o.upperPath(s.ID), Type: "bind", Options: []string{ roFlag, @@ -315,15 +316,15 @@ func (o *snapshotter) mounts(active storage.Active) []mount.Mount { } var options []string - if !active.Readonly { + if s.Kind == snapshot.KindActive { options = append(options, - fmt.Sprintf("workdir=%s", o.workPath(active.ID)), - fmt.Sprintf("upperdir=%s", o.upperPath(active.ID)), + fmt.Sprintf("workdir=%s", o.workPath(s.ID)), + fmt.Sprintf("upperdir=%s", o.upperPath(s.ID)), ) - } else if len(active.ParentIDs) == 1 { + } else if len(s.ParentIDs) == 1 { return []mount.Mount{ { - Source: o.upperPath(active.ParentIDs[0]), + Source: o.upperPath(s.ParentIDs[0]), Type: "bind", Options: []string{ "ro", @@ -333,9 +334,9 @@ func (o *snapshotter) mounts(active storage.Active) []mount.Mount { } } - parentPaths := make([]string, len(active.ParentIDs)) - for i := range active.ParentIDs { - parentPaths[i] = o.upperPath(active.ParentIDs[i]) + parentPaths := make([]string, len(s.ParentIDs)) + for i := range s.ParentIDs { + parentPaths[i] = o.upperPath(s.ParentIDs[i]) } options = append(options, fmt.Sprintf("lowerdir=%s", strings.Join(parentPaths, ":"))) diff --git a/snapshot/overlay/overlay_test.go b/snapshot/overlay/overlay_test.go index f80d11559..1bd9d923d 100644 --- a/snapshot/overlay/overlay_test.go +++ b/snapshot/overlay/overlay_test.go @@ -158,12 +158,12 @@ func getBasePath(ctx context.Context, sn snapshot.Snapshotter, root, key string) } defer t.Rollback() - active, err := storage.GetActive(ctx, key) + s, err := storage.GetSnapshot(ctx, key) if err != nil { panic(err) } - return filepath.Join(root, "snapshots", active.ID) + return filepath.Join(root, "snapshots", s.ID) } func getParents(ctx context.Context, sn snapshot.Snapshotter, root, key string) []string { @@ -173,13 +173,13 @@ func getParents(ctx context.Context, sn snapshot.Snapshotter, root, key string) panic(err) } defer t.Rollback() - active, err := storage.GetActive(ctx, key) + s, err := storage.GetSnapshot(ctx, key) if err != nil { panic(err) } - parents := make([]string, len(active.ParentIDs)) - for i := range active.ParentIDs { - parents[i] = filepath.Join(root, "snapshots", active.ParentIDs[i], "fs") + parents := make([]string, len(s.ParentIDs)) + for i := range s.ParentIDs { + parents[i] = filepath.Join(root, "snapshots", s.ParentIDs[i], "fs") } return parents } diff --git a/snapshot/snapshotter.go b/snapshot/snapshotter.go index 6bd1447ed..c2cd73fc8 100644 --- a/snapshot/snapshotter.go +++ b/snapshot/snapshotter.go @@ -11,16 +11,29 @@ type Kind int // definitions of snapshot kinds const ( - KindActive Kind = iota + KindView Kind = iota + 1 + KindActive KindCommitted ) +func (k Kind) String() string { + switch k { + case KindView: + return "View" + case KindActive: + return "Active" + case KindCommitted: + return "Committed" + default: + return "Unknown" + } +} + // Info provides information about a particular snapshot. type Info struct { - Name string // name or key of snapshot - Parent string // name of parent snapshot - Kind Kind // active or committed snapshot - Readonly bool // true if readonly, only valid for active + Kind Kind // active or committed snapshot + Name string // name or key of snapshot + Parent string // name of parent snapshot } // Usage defines statistics for disk resources consumed by the snapshot. diff --git a/snapshot/storage/bolt.go b/snapshot/storage/bolt.go index f6dc80161..abe997c29 100644 --- a/snapshot/storage/bolt.go +++ b/snapshot/storage/bolt.go @@ -79,10 +79,9 @@ func GetInfo(ctx context.Context, key string) (string, snapshot.Info, snapshot.U } return fmt.Sprint(ss.ID), snapshot.Info{ - Name: key, - Parent: ss.Parent, - Kind: fromProtoKind(ss.Kind), - Readonly: ss.Readonly, + Name: key, + Parent: ss.Parent, + Kind: snapshot.Kind(ss.Kind), }, usage, nil } @@ -102,22 +101,64 @@ func WalkInfo(ctx context.Context, fn func(context.Context, snapshot.Info) error } info := snapshot.Info{ - Name: string(k), - Parent: ss.Parent, - Kind: fromProtoKind(ss.Kind), - Readonly: ss.Readonly, + Name: string(k), + Parent: ss.Parent, + Kind: snapshot.Kind(ss.Kind), } return fn(ctx, info) }) }) } -// CreateActive creates a new active snapshot transaction referenced by -// the provided key. The new active snapshot will have the provided -// parent. If the readonly option is given, the active snapshot will be -// marked as readonly and can only be removed, and not committed. The -// provided context must contain a writable transaction. -func CreateActive(ctx context.Context, key, parent string, readonly bool) (a Active, err error) { +// GetSnapshot returns the metadata for the active or view snapshot transaction +// referenced by the given key. Requires a context with a storage transaction. +func GetSnapshot(ctx context.Context, key string) (s Snapshot, err error) { + err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { + b := bkt.Get([]byte(key)) + if len(b) == 0 { + return errors.Wrapf(errdefs.ErrNotFound, "snapshot %v", key) + } + + var ss db.Snapshot + if err := proto.Unmarshal(b, &ss); err != nil { + return errors.Wrap(err, "failed to unmarshal snapshot") + } + + if ss.Kind != db.KindActive && ss.Kind != db.KindView { + return errors.Wrapf(errdefs.ErrFailedPrecondition, "requested snapshot %v not active or view", key) + } + + s.ID = fmt.Sprintf("%d", ss.ID) + s.Kind = snapshot.Kind(ss.Kind) + + if ss.Parent != "" { + var parent db.Snapshot + if err := getSnapshot(bkt, ss.Parent, &parent); err != nil { + return errors.Wrap(err, "failed to get parent snapshot") + } + + s.ParentIDs, err = parents(bkt, &parent) + if err != nil { + return errors.Wrap(err, "failed to get parent chain") + } + } + return nil + }) + if err != nil { + return Snapshot{}, err + } + + return +} + +// CreateSnapshot inserts a record for an active or view snapshot with the provided parent. +func CreateSnapshot(ctx context.Context, kind snapshot.Kind, key, parent string) (s Snapshot, err error) { + switch kind { + case snapshot.KindActive, snapshot.KindView: + default: + return Snapshot{}, errors.Wrapf(errdefs.ErrInvalidArgument, "snapshot type %v invalid; only snapshots of type Active or View can be created", kind) + } + err = createBucketIfNotExists(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { var ( parentS *db.Snapshot @@ -143,10 +184,9 @@ func CreateActive(ctx context.Context, key, parent string, readonly bool) (a Act } ss := db.Snapshot{ - ID: id, - Parent: parent, - Kind: db.KindActive, - Readonly: readonly, + ID: id, + Parent: parent, + Kind: db.Kind(kind), } if err := putSnapshot(bkt, key, &ss); err != nil { return err @@ -159,59 +199,18 @@ func CreateActive(ctx context.Context, key, parent string, readonly bool) (a Act return errors.Wrap(err, "failed to write parent link") } - a.ParentIDs, err = parents(bkt, parentS) + s.ParentIDs, err = parents(bkt, parentS) if err != nil { return errors.Wrap(err, "failed to get parent chain") } } - a.ID = fmt.Sprintf("%d", id) - a.Readonly = readonly - + s.ID = fmt.Sprintf("%d", id) + s.Kind = kind return nil }) if err != nil { - return Active{}, err - } - - return -} - -// GetActive returns the metadata for the active snapshot transaction referenced -// by the given key. Requires a context with a storage transaction. -func GetActive(ctx context.Context, key string) (a Active, err error) { - err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { - b := bkt.Get([]byte(key)) - if len(b) == 0 { - return errors.Wrapf(errdefs.ErrNotFound, "snapshot %v", key) - } - - var ss db.Snapshot - if err := proto.Unmarshal(b, &ss); err != nil { - return errors.Wrap(err, "failed to unmarshal snapshot") - } - if ss.Kind != db.KindActive { - return errors.Wrapf(errdefs.ErrFailedPrecondition, "requested snapshot %v not active", key) - } - - a.ID = fmt.Sprintf("%d", ss.ID) - a.Readonly = ss.Readonly - - if ss.Parent != "" { - var parent db.Snapshot - if err := getSnapshot(bkt, ss.Parent, &parent); err != nil { - return errors.Wrap(err, "failed to get parent snapshot") - } - - a.ParentIDs, err = parents(bkt, &parent) - if err != nil { - return errors.Wrap(err, "failed to get parent chain") - } - } - return nil - }) - if err != nil { - return Active{}, err + return Snapshot{}, err } return @@ -255,7 +254,7 @@ func Remove(ctx context.Context, key string) (id string, k snapshot.Kind, err er } id = fmt.Sprintf("%d", ss.ID) - k = fromProtoKind(ss.Kind) + k = snapshot.Kind(ss.Kind) return nil }) @@ -283,12 +282,8 @@ func CommitActive(ctx context.Context, key, name string, usage snapshot.Usage) ( if ss.Kind != db.KindActive { return errors.Wrapf(errdefs.ErrFailedPrecondition, "snapshot %v is not active", name) } - if ss.Readonly { - return errors.Errorf("active snapshot is readonly") - } ss.Kind = db.KindCommitted - ss.Readonly = true ss.Inodes = usage.Inodes ss.Size_ = usage.Size @@ -354,13 +349,6 @@ func createBucketIfNotExists(ctx context.Context, fn func(context.Context, *bolt return fn(ctx, sbkt, pbkt) } -func fromProtoKind(k db.Kind) snapshot.Kind { - if k == db.KindActive { - return snapshot.KindActive - } - return snapshot.KindCommitted -} - func parents(bkt *bolt.Bucket, parent *db.Snapshot) (parents []string, err error) { for { parents = append(parents, fmt.Sprintf("%d", parent.ID)) diff --git a/snapshot/storage/bolt_test.go b/snapshot/storage/bolt_test.go index 32454c351..17d1a9596 100644 --- a/snapshot/storage/bolt_test.go +++ b/snapshot/storage/bolt_test.go @@ -5,6 +5,8 @@ import ( "testing" // Does not require root but flag must be defined for snapshot tests + "github.com/containerd/containerd/snapshot" + "github.com/containerd/containerd/snapshot/storage/proto" _ "github.com/containerd/containerd/testutil" ) @@ -14,6 +16,21 @@ func TestMetastore(t *testing.T) { }) } +// TestKidnConversion ensures we can blindly cast from protobuf types. +func TestKindConversion(t *testing.T) { + for _, testcase := range []snapshot.Kind{ + snapshot.KindView, + snapshot.KindActive, + snapshot.KindCommitted, + } { + cast := proto.Kind(testcase) + uncast := snapshot.Kind(cast) + if uncast != testcase { + t.Fatalf("kind value cast failed: %v != %v", uncast, testcase) + } + } +} + func BenchmarkSuite(b *testing.B) { Benchmarks(b, "BoltDBBench", func(root string) (*MetaStore, error) { return NewMetaStore(filepath.Join(root, "metadata.db")) diff --git a/snapshot/storage/metastore.go b/snapshot/storage/metastore.go index c223d40d5..692931a3c 100644 --- a/snapshot/storage/metastore.go +++ b/snapshot/storage/metastore.go @@ -9,6 +9,7 @@ import ( "context" "github.com/boltdb/bolt" + "github.com/containerd/containerd/snapshot" "github.com/pkg/errors" ) @@ -26,15 +27,16 @@ type Transactor interface { Rollback() error } -// Active hold the metadata for an active snapshot transaction. The ParentIDs -// hold the snapshot identifiers for the committed snapshots this active is -// based on. The ParentIDs are ordered from the lowest base to highest, meaning -// they should be applied in order from the first index to the last index. The -// last index should always be considered the active snapshots immediate parent. -type Active struct { +// Snapshot hold the metadata for an active or view snapshot transaction. The +// ParentIDs hold the snapshot identifiers for the committed snapshots this +// active or view is based on. The ParentIDs are ordered from the lowest base +// to highest, meaning they should be applied in order from the first index to +// the last index. The last index should always be considered the active +// snapshots immediate parent. +type Snapshot struct { + Kind snapshot.Kind ID string ParentIDs []string - Readonly bool } // MetaStore is used to store metadata related to a snapshot driver. The diff --git a/snapshot/storage/metastore_bench_test.go b/snapshot/storage/metastore_bench_test.go index 21406f09c..18b2fd120 100644 --- a/snapshot/storage/metastore_bench_test.go +++ b/snapshot/storage/metastore_bench_test.go @@ -106,14 +106,14 @@ func openCloseReadonly(b *testing.B, name string, metaFn metaFactory) func(b *te } func createActiveFromBase(ctx context.Context, ms *MetaStore, active, base string) error { - if _, err := CreateActive(ctx, "bottom", "", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "bottom", ""); err != nil { return err } if _, err := CommitActive(ctx, "bottom", base, snapshot.Usage{}); err != nil { return err } - _, err := CreateActive(ctx, active, base, false) + _, err := CreateSnapshot(ctx, snapshot.KindActive, active, base) return err } @@ -150,7 +150,7 @@ func statCommittedBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { func createActiveBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { for i := 0; i < b.N; i++ { - if _, err := CreateActive(ctx, "active", "", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "active", ""); err != nil { b.Fatal(err) } b.StopTimer() @@ -164,7 +164,7 @@ func createActiveBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { func removeBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { for i := 0; i < b.N; i++ { b.StopTimer() - if _, err := CreateActive(ctx, "active", "", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "active", ""); err != nil { b.Fatal(err) } b.StartTimer() @@ -177,7 +177,7 @@ func removeBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { func commitBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { b.StopTimer() for i := 0; i < b.N; i++ { - if _, err := CreateActive(ctx, "active", "", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "active", ""); err != nil { b.Fatal(err) } b.StartTimer() @@ -194,7 +194,7 @@ func commitBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { func getActiveBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { var base string for i := 1; i <= 10; i++ { - if _, err := CreateActive(ctx, "tmp", base, false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "tmp", base); err != nil { b.Fatalf("create active failed: %+v", err) } base = fmt.Sprintf("base-%d", i) @@ -204,13 +204,13 @@ func getActiveBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) { } - if _, err := CreateActive(ctx, "active", base, false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "active", base); err != nil { b.Fatalf("create active failed: %+v", err) } b.ResetTimer() for i := 0; i < b.N; i++ { - if _, err := GetActive(ctx, "active"); err != nil { + if _, err := GetSnapshot(ctx, "active"); err != nil { b.Fatal(err) } } diff --git a/snapshot/storage/metastore_test.go b/snapshot/storage/metastore_test.go index cf22e8811..9aa164f66 100644 --- a/snapshot/storage/metastore_test.go +++ b/snapshot/storage/metastore_test.go @@ -24,10 +24,10 @@ func MetaStoreSuite(t *testing.T, name string, meta func(root string) (*MetaStor t.Run("GetInfoNotExist", makeTest(t, name, meta, inReadTransaction(testGetInfoNotExist, basePopulate))) t.Run("GetInfoEmptyDB", makeTest(t, name, meta, inReadTransaction(testGetInfoNotExist, nil))) t.Run("Walk", makeTest(t, name, meta, inReadTransaction(testWalk, basePopulate))) - t.Run("GetActive", makeTest(t, name, meta, testGetActive)) - t.Run("GetActiveNotExist", makeTest(t, name, meta, inReadTransaction(testGetActiveNotExist, basePopulate))) - t.Run("GetActiveCommitted", makeTest(t, name, meta, inReadTransaction(testGetActiveCommitted, basePopulate))) - t.Run("GetActiveEmptyDB", makeTest(t, name, meta, inReadTransaction(testGetActiveNotExist, basePopulate))) + t.Run("GetSnapshot", makeTest(t, name, meta, testGetSnapshot)) + t.Run("GetSnapshotNotExist", makeTest(t, name, meta, inReadTransaction(testGetSnapshotNotExist, basePopulate))) + t.Run("GetSnapshotCommitted", makeTest(t, name, meta, inReadTransaction(testGetSnapshotCommitted, basePopulate))) + t.Run("GetSnapshotEmptyDB", makeTest(t, name, meta, inReadTransaction(testGetSnapshotNotExist, basePopulate))) t.Run("CreateActive", makeTest(t, name, meta, inWriteTransaction(testCreateActive))) t.Run("CreateActiveNotExist", makeTest(t, name, meta, inWriteTransaction(testCreateActiveNotExist))) t.Run("CreateActiveExist", makeTest(t, name, meta, inWriteTransaction(testCreateActiveExist))) @@ -36,7 +36,7 @@ func MetaStoreSuite(t *testing.T, name string, meta func(root string) (*MetaStor t.Run("CommitNotExist", makeTest(t, name, meta, inWriteTransaction(testCommitExist))) t.Run("CommitExist", makeTest(t, name, meta, inWriteTransaction(testCommitExist))) t.Run("CommitCommitted", makeTest(t, name, meta, inWriteTransaction(testCommitCommitted))) - t.Run("CommitReadonly", makeTest(t, name, meta, inWriteTransaction(testCommitReadonly))) + t.Run("CommitViewFails", makeTest(t, name, meta, inWriteTransaction(testCommitViewFails))) t.Run("Remove", makeTest(t, name, meta, inWriteTransaction(testRemove))) t.Run("RemoveNotExist", makeTest(t, name, meta, inWriteTransaction(testRemoveNotExist))) t.Run("RemoveWithChildren", makeTest(t, name, meta, inWriteTransaction(testRemoveWithChildren))) @@ -126,31 +126,31 @@ func inWriteTransaction(fn testFunc) testFunc { // - "active-4": readonly active without parent" // - "active-5": readonly active with parent "committed-2" func basePopulate(ctx context.Context, ms *MetaStore) error { - if _, err := CreateActive(ctx, "committed-tmp-1", "", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "committed-tmp-1", ""); err != nil { return errors.Wrap(err, "failed to create active") } if _, err := CommitActive(ctx, "committed-tmp-1", "committed-1", snapshot.Usage{Size: 1}); err != nil { return errors.Wrap(err, "failed to create active") } - if _, err := CreateActive(ctx, "committed-tmp-2", "committed-1", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "committed-tmp-2", "committed-1"); err != nil { return errors.Wrap(err, "failed to create active") } if _, err := CommitActive(ctx, "committed-tmp-2", "committed-2", snapshot.Usage{Size: 2}); err != nil { return errors.Wrap(err, "failed to create active") } - if _, err := CreateActive(ctx, "active-1", "", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "active-1", ""); err != nil { return errors.Wrap(err, "failed to create active") } - if _, err := CreateActive(ctx, "active-2", "committed-1", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "active-2", "committed-1"); err != nil { return errors.Wrap(err, "failed to create active") } - if _, err := CreateActive(ctx, "active-3", "committed-2", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "active-3", "committed-2"); err != nil { return errors.Wrap(err, "failed to create active") } - if _, err := CreateActive(ctx, "active-4", "", true); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindView, "view-1", ""); err != nil { return errors.Wrap(err, "failed to create active") } - if _, err := CreateActive(ctx, "active-5", "committed-2", true); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindView, "view-2", "committed-2"); err != nil { return errors.Wrap(err, "failed to create active") } return nil @@ -158,46 +158,39 @@ func basePopulate(ctx context.Context, ms *MetaStore) error { var baseInfo = map[string]snapshot.Info{ "committed-1": { - Name: "committed-1", - Parent: "", - Kind: snapshot.KindCommitted, - Readonly: true, + Name: "committed-1", + Parent: "", + Kind: snapshot.KindCommitted, }, "committed-2": { - Name: "committed-2", - Parent: "committed-1", - Kind: snapshot.KindCommitted, - Readonly: true, + Name: "committed-2", + Parent: "committed-1", + Kind: snapshot.KindCommitted, }, "active-1": { - Name: "active-1", - Parent: "", - Kind: snapshot.KindActive, - Readonly: false, + Name: "active-1", + Parent: "", + Kind: snapshot.KindActive, }, "active-2": { - Name: "active-2", - Parent: "committed-1", - Kind: snapshot.KindActive, - Readonly: false, + Name: "active-2", + Parent: "committed-1", + Kind: snapshot.KindActive, }, "active-3": { - Name: "active-3", - Parent: "committed-2", - Kind: snapshot.KindActive, - Readonly: false, + Name: "active-3", + Parent: "committed-2", + Kind: snapshot.KindActive, }, - "active-4": { - Name: "active-4", - Parent: "", - Kind: snapshot.KindActive, - Readonly: true, + "view-1": { + Name: "view-1", + Parent: "", + Kind: snapshot.KindView, }, - "active-5": { - Name: "active-5", - Parent: "committed-2", - Kind: snapshot.KindActive, - Readonly: true, + "view-2": { + Name: "view-2", + Parent: "committed-2", + Kind: snapshot.KindView, }, } @@ -267,10 +260,10 @@ func testWalk(ctx context.Context, t *testing.T, ms *MetaStore) { assert.Equal(t, baseInfo, found) } -func testGetActive(ctx context.Context, t *testing.T, ms *MetaStore) { - activeMap := map[string]Active{} +func testGetSnapshot(ctx context.Context, t *testing.T, ms *MetaStore) { + snapshotMap := map[string]Snapshot{} populate := func(ctx context.Context, ms *MetaStore) error { - if _, err := CreateActive(ctx, "committed-tmp-1", "", false); err != nil { + if _, err := CreateSnapshot(ctx, snapshot.KindActive, "committed-tmp-1", ""); err != nil { return errors.Wrap(err, "failed to create active") } if _, err := CommitActive(ctx, "committed-tmp-1", "committed-1", snapshot.Usage{}); err != nil { @@ -278,77 +271,79 @@ func testGetActive(ctx context.Context, t *testing.T, ms *MetaStore) { } for _, opts := range []struct { - Name string - Parent string - Readonly bool + Kind snapshot.Kind + Name string + Parent string }{ { Name: "active-1", + Kind: snapshot.KindActive, }, { Name: "active-2", Parent: "committed-1", + Kind: snapshot.KindActive, }, { - Name: "active-3", - Readonly: true, + Name: "view-1", + Kind: snapshot.KindView, }, { - Name: "active-4", - Parent: "committed-1", - Readonly: true, + Name: "view-2", + Parent: "committed-1", + Kind: snapshot.KindView, }, } { - active, err := CreateActive(ctx, opts.Name, opts.Parent, opts.Readonly) + active, err := CreateSnapshot(ctx, opts.Kind, opts.Name, opts.Parent) if err != nil { return errors.Wrap(err, "failed to create active") } - activeMap[opts.Name] = active + snapshotMap[opts.Name] = active } return nil } test := func(ctx context.Context, t *testing.T, ms *MetaStore) { - for key, expected := range activeMap { - active, err := GetActive(ctx, key) + for key, expected := range snapshotMap { + s, err := GetSnapshot(ctx, key) if err != nil { t.Fatalf("Failed to get active: %+v", err) } - assert.Equal(t, expected, active) + assert.Equal(t, expected, s) } } inReadTransaction(test, populate)(ctx, t, ms) } -func testGetActiveCommitted(ctx context.Context, t *testing.T, ms *MetaStore) { - _, err := GetActive(ctx, "committed-1") +func testGetSnapshotCommitted(ctx context.Context, t *testing.T, ms *MetaStore) { + _, err := GetSnapshot(ctx, "committed-1") assertNotActive(t, err) } -func testGetActiveNotExist(ctx context.Context, t *testing.T, ms *MetaStore) { - _, err := GetActive(ctx, "active-not-exist") +func testGetSnapshotNotExist(ctx context.Context, t *testing.T, ms *MetaStore) { + _, err := GetSnapshot(ctx, "active-not-exist") assertNotExist(t, err) } func testCreateActive(ctx context.Context, t *testing.T, ms *MetaStore) { - a1, err := CreateActive(ctx, "active-1", "", false) + a1, err := CreateSnapshot(ctx, snapshot.KindActive, "active-1", "") if err != nil { t.Fatal(err) } - if a1.Readonly { + if a1.Kind != snapshot.KindActive { t.Fatal("Expected writable active") } - a2, err := CreateActive(ctx, "active-2", "", true) + a2, err := CreateSnapshot(ctx, snapshot.KindView, "view-1", "") if err != nil { t.Fatal(err) } if a2.ID == a1.ID { t.Fatal("Returned active identifiers must be unique") } - if !a2.Readonly { - t.Fatal("Expected readonly active") + if a2.Kind != snapshot.KindView { + t.Fatal("Expected a view") } commitID, err := CommitActive(ctx, "active-1", "committed-1", snapshot.Usage{}) @@ -359,7 +354,7 @@ func testCreateActive(ctx context.Context, t *testing.T, ms *MetaStore) { t.Fatal("Snapshot identifier must not change on commit") } - a3, err := CreateActive(ctx, "active-3", "committed-1", false) + a3, err := CreateSnapshot(ctx, snapshot.KindActive, "active-3", "committed-1") if err != nil { t.Fatal(err) } @@ -372,11 +367,11 @@ func testCreateActive(ctx context.Context, t *testing.T, ms *MetaStore) { if a3.ParentIDs[0] != commitID { t.Fatal("Expected active parent to be same as commit ID") } - if a3.Readonly { + if a3.Kind != snapshot.KindActive { t.Fatal("Expected writable active") } - a4, err := CreateActive(ctx, "active-4", "committed-1", true) + a4, err := CreateSnapshot(ctx, snapshot.KindView, "view-2", "committed-1") if err != nil { t.Fatal(err) } @@ -389,8 +384,8 @@ func testCreateActive(ctx context.Context, t *testing.T, ms *MetaStore) { if a3.ParentIDs[0] != commitID { t.Fatal("Expected active parent to be same as commit ID") } - if !a4.Readonly { - t.Fatal("Expected readonly active") + if a4.Kind != snapshot.KindView { + t.Fatal("Expected a view") } } @@ -398,14 +393,14 @@ func testCreateActiveExist(ctx context.Context, t *testing.T, ms *MetaStore) { if err := basePopulate(ctx, ms); err != nil { t.Fatalf("Populate failed: %+v", err) } - _, err := CreateActive(ctx, "active-1", "", false) + _, err := CreateSnapshot(ctx, snapshot.KindActive, "active-1", "") assertExist(t, err) - _, err = CreateActive(ctx, "committed-1", "", false) + _, err = CreateSnapshot(ctx, snapshot.KindActive, "committed-1", "") assertExist(t, err) } func testCreateActiveNotExist(ctx context.Context, t *testing.T, ms *MetaStore) { - _, err := CreateActive(ctx, "active-1", "does-not-exist", false) + _, err := CreateSnapshot(ctx, snapshot.KindActive, "active-1", "does-not-exist") assertNotExist(t, err) } @@ -413,16 +408,16 @@ func testCreateActiveFromActive(ctx context.Context, t *testing.T, ms *MetaStore if err := basePopulate(ctx, ms); err != nil { t.Fatalf("Populate failed: %+v", err) } - _, err := CreateActive(ctx, "active-new", "active-1", false) + _, err := CreateSnapshot(ctx, snapshot.KindActive, "active-new", "active-1") assertNotCommitted(t, err) } func testCommit(ctx context.Context, t *testing.T, ms *MetaStore) { - a1, err := CreateActive(ctx, "active-1", "", false) + a1, err := CreateSnapshot(ctx, snapshot.KindActive, "active-1", "") if err != nil { t.Fatal(err) } - if a1.Readonly { + if a1.Kind != snapshot.KindActive { t.Fatal("Expected writable active") } @@ -434,9 +429,9 @@ func testCommit(ctx context.Context, t *testing.T, ms *MetaStore) { t.Fatal("Snapshot identifier must not change on commit") } - _, err = GetActive(ctx, "active-1") + _, err = GetSnapshot(ctx, "active-1") assertNotExist(t, err) - _, err = GetActive(ctx, "committed-1") + _, err = GetSnapshot(ctx, "committed-1") assertNotActive(t, err) } @@ -461,18 +456,18 @@ func testCommitCommitted(ctx context.Context, t *testing.T, ms *MetaStore) { assertNotActive(t, err) } -func testCommitReadonly(ctx context.Context, t *testing.T, ms *MetaStore) { +func testCommitViewFails(ctx context.Context, t *testing.T, ms *MetaStore) { if err := basePopulate(ctx, ms); err != nil { t.Fatalf("Populate failed: %+v", err) } - _, err := CommitActive(ctx, "active-5", "committed-3", snapshot.Usage{}) + _, err := CommitActive(ctx, "view-1", "committed-3", snapshot.Usage{}) if err == nil { t.Fatal("Expected error committing readonly active") } } func testRemove(ctx context.Context, t *testing.T, ms *MetaStore) { - a1, err := CreateActive(ctx, "active-1", "", false) + a1, err := CreateSnapshot(ctx, snapshot.KindActive, "active-1", "") if err != nil { t.Fatal(err) } @@ -485,12 +480,12 @@ func testRemove(ctx context.Context, t *testing.T, ms *MetaStore) { t.Fatal("Snapshot identifier must not change on commit") } - a2, err := CreateActive(ctx, "active-2", "committed-1", true) + a2, err := CreateSnapshot(ctx, snapshot.KindView, "view-1", "committed-1") if err != nil { t.Fatal(err) } - a3, err := CreateActive(ctx, "active-3", "committed-1", true) + a3, err := CreateSnapshot(ctx, snapshot.KindView, "view-2", "committed-1") if err != nil { t.Fatal(err) } @@ -498,26 +493,26 @@ func testRemove(ctx context.Context, t *testing.T, ms *MetaStore) { _, _, err = Remove(ctx, "active-1") assertNotExist(t, err) - r3, k3, err := Remove(ctx, "active-3") + r3, k3, err := Remove(ctx, "view-2") if err != nil { t.Fatal(err) } if r3 != a3.ID { t.Fatal("Expected remove ID to match create ID") } - if k3 != snapshot.KindActive { - t.Fatalf("Expected active kind, got %v", k3) + if k3 != snapshot.KindView { + t.Fatalf("Expected view kind, got %v", k3) } - r2, k2, err := Remove(ctx, "active-2") + r2, k2, err := Remove(ctx, "view-1") if err != nil { t.Fatal(err) } if r2 != a2.ID { t.Fatal("Expected remove ID to match create ID") } - if k2 != snapshot.KindActive { - t.Fatalf("Expected active kind, got %v", k2) + if k2 != snapshot.KindView { + t.Fatalf("Expected view kind, got %v", k2) } r1, k1, err := Remove(ctx, "committed-1") diff --git a/snapshot/storage/proto/record.pb.go b/snapshot/storage/proto/record.pb.go index b42b674f6..bfaa67d0b 100644 --- a/snapshot/storage/proto/record.pb.go +++ b/snapshot/storage/proto/record.pb.go @@ -34,23 +34,26 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto1.GoGoProtoPackageIsVersion2 // please upgrade the proto package -// Kind defines the kind of snapshot. type Kind int32 const ( - // KindActive represents an active snapshot - KindActive Kind = 0 - // KindCommitted represents a committed immutable snapshot - KindCommitted Kind = 1 + KindUnknown Kind = 0 + KindView Kind = 1 + KindActive Kind = 2 + KindCommitted Kind = 3 ) var Kind_name = map[int32]string{ - 0: "ACTIVE", - 1: "COMMITTED", + 0: "UNKNOWN", + 1: "VIEW", + 2: "ACTIVE", + 3: "COMMITTED", } var Kind_value = map[string]int32{ - "ACTIVE": 0, - "COMMITTED": 1, + "UNKNOWN": 0, + "VIEW": 1, + "ACTIVE": 2, + "COMMITTED": 3, } func (x Kind) String() string { @@ -61,10 +64,9 @@ func (Kind) EnumDescriptor() ([]byte, []int) { return fileDescriptorRecord, []in // Snapshot defines the storage type for a snapshot in the // metadata store. type Snapshot struct { - ID uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - Parent string `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` - Kind Kind `protobuf:"varint,4,opt,name=kind,proto3,enum=containerd.snapshot.v1.Kind" json:"kind,omitempty"` - Readonly bool `protobuf:"varint,5,opt,name=readonly,proto3" json:"readonly,omitempty"` + ID uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Parent string `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` + Kind Kind `protobuf:"varint,4,opt,name=kind,proto3,enum=containerd.snapshot.v1.Kind" json:"kind,omitempty"` // inodes stores the number inodes in use for the snapshot. // // Only valid for committed snapshots. @@ -115,16 +117,6 @@ func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintRecord(dAtA, i, uint64(m.Kind)) } - if m.Readonly { - dAtA[i] = 0x28 - i++ - if m.Readonly { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - } if m.Inodes != 0 { dAtA[i] = 0x30 i++ @@ -178,9 +170,6 @@ func (m *Snapshot) Size() (n int) { if m.Kind != 0 { n += 1 + sovRecord(uint64(m.Kind)) } - if m.Readonly { - n += 2 - } if m.Inodes != 0 { n += 1 + sovRecord(uint64(m.Inodes)) } @@ -211,7 +200,6 @@ func (this *Snapshot) String() string { `ID:` + fmt.Sprintf("%v", this.ID) + `,`, `Parent:` + fmt.Sprintf("%v", this.Parent) + `,`, `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, - `Readonly:` + fmt.Sprintf("%v", this.Readonly) + `,`, `Inodes:` + fmt.Sprintf("%v", this.Inodes) + `,`, `Size_:` + fmt.Sprintf("%v", this.Size_) + `,`, `}`, @@ -322,26 +310,6 @@ func (m *Snapshot) Unmarshal(dAtA []byte) error { break } } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Readonly", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowRecord - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Readonly = bool(v != 0) case 6: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Inodes", wireType) @@ -511,26 +479,28 @@ func init() { } var fileDescriptorRecord = []byte{ - // 334 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xbb, 0x4e, 0xf3, 0x30, - 0x1c, 0xc5, 0xe3, 0x7c, 0xf9, 0x42, 0x6b, 0x41, 0x55, 0x2c, 0x54, 0x59, 0x11, 0x32, 0x16, 0x53, - 0xc4, 0x90, 0x70, 0x79, 0x82, 0xde, 0x86, 0xaa, 0xaa, 0x90, 0x42, 0xc5, 0x9e, 0xc6, 0x56, 0x6a, - 0x41, 0xed, 0xca, 0x31, 0x95, 0x60, 0x62, 0x44, 0x7d, 0x87, 0x4e, 0xf0, 0x08, 0x4c, 0x3c, 0x41, - 0x47, 0x46, 0x26, 0x44, 0xf3, 0x24, 0x28, 0x69, 0xb9, 0x0c, 0x6c, 0xe7, 0xf7, 0xf7, 0x4f, 0xe7, - 0x48, 0x86, 0x9d, 0x54, 0x98, 0xf1, 0xcd, 0x28, 0x48, 0xd4, 0x24, 0x4c, 0x94, 0x34, 0xb1, 0x90, - 0x5c, 0xb3, 0xdf, 0x31, 0x93, 0xf1, 0x34, 0x1b, 0x2b, 0x13, 0x66, 0x46, 0xe9, 0x38, 0xe5, 0xe1, - 0x54, 0x2b, 0xa3, 0x42, 0xcd, 0x13, 0xa5, 0x59, 0x50, 0x02, 0x6a, 0xfc, 0xf8, 0xc1, 0x97, 0x1f, - 0xcc, 0x4e, 0xbc, 0xbd, 0x54, 0xa5, 0x6a, 0xed, 0x17, 0x69, 0x6d, 0x1f, 0x3e, 0x03, 0x58, 0xb9, - 0xd8, 0x58, 0xa8, 0x01, 0x6d, 0xc1, 0x30, 0xa0, 0xc0, 0x77, 0x5a, 0x6e, 0xfe, 0x7e, 0x60, 0xf7, - 0x3a, 0x91, 0x2d, 0x18, 0x6a, 0x40, 0x77, 0x1a, 0x6b, 0x2e, 0x0d, 0xb6, 0x29, 0xf0, 0xab, 0xd1, - 0x86, 0xd0, 0x31, 0x74, 0xae, 0x84, 0x64, 0xd8, 0xa1, 0xc0, 0xaf, 0x9d, 0xee, 0x07, 0x7f, 0x2f, - 0x07, 0x7d, 0x21, 0x59, 0x54, 0x9a, 0xc8, 0x83, 0x15, 0xcd, 0x63, 0xa6, 0xe4, 0xf5, 0x2d, 0xfe, - 0x4f, 0x81, 0x5f, 0x89, 0xbe, 0xb9, 0x58, 0x11, 0x52, 0x31, 0x9e, 0x61, 0x97, 0x02, 0xff, 0x5f, - 0xb4, 0x21, 0x84, 0xa0, 0x93, 0x89, 0x3b, 0x8e, 0xb7, 0xca, 0x6b, 0x99, 0x8f, 0x22, 0xe8, 0xf4, - 0xd7, 0x7d, 0x6e, 0xb3, 0x3d, 0xec, 0x5d, 0x76, 0xeb, 0x96, 0x57, 0x9b, 0x2f, 0x28, 0x2c, 0xae, - 0xcd, 0xc4, 0x88, 0x19, 0x47, 0x14, 0x56, 0xdb, 0xe7, 0x83, 0x41, 0x6f, 0x38, 0xec, 0x76, 0xea, - 0xc0, 0xdb, 0x9d, 0x2f, 0xe8, 0x4e, 0xf1, 0xdc, 0x56, 0x93, 0x89, 0x30, 0x86, 0x33, 0x6f, 0xfb, - 0xe1, 0x91, 0x58, 0x2f, 0x4f, 0xa4, 0xec, 0x6a, 0xe1, 0xe5, 0x8a, 0x58, 0x6f, 0x2b, 0x62, 0xdd, - 0xe7, 0x04, 0x2c, 0x73, 0x02, 0x5e, 0x73, 0x02, 0x3e, 0x72, 0x02, 0x46, 0x6e, 0xf9, 0x57, 0x67, - 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xae, 0x6e, 0x6e, 0xcd, 0xa1, 0x01, 0x00, 0x00, + // 364 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xbb, 0xae, 0xd3, 0x30, + 0x18, 0xc7, 0xe3, 0x9c, 0x28, 0xe7, 0xd4, 0x94, 0x12, 0x2c, 0x14, 0x45, 0x51, 0x65, 0x2c, 0xa6, + 0x88, 0x21, 0xe1, 0xf2, 0x04, 0xbd, 0x0d, 0x51, 0xd5, 0x56, 0x0a, 0xbd, 0xcc, 0x69, 0x6c, 0xa5, + 0x56, 0x55, 0xbb, 0x4a, 0x4c, 0x2b, 0x31, 0x31, 0x56, 0x79, 0x02, 0x96, 0x4c, 0xf0, 0x14, 0x3c, + 0x41, 0x47, 0x46, 0x26, 0x44, 0xf3, 0x24, 0x28, 0x69, 0x11, 0x0c, 0x67, 0xfb, 0x5f, 0x7e, 0xf6, + 0xf7, 0xe9, 0x83, 0xc3, 0x94, 0xab, 0xcd, 0xc7, 0xb5, 0x9f, 0xc8, 0x5d, 0x90, 0x48, 0xa1, 0x62, + 0x2e, 0x58, 0x46, 0xff, 0x97, 0xb9, 0x88, 0xf7, 0xf9, 0x46, 0xaa, 0x20, 0x57, 0x32, 0x8b, 0x53, + 0x16, 0xec, 0x33, 0xa9, 0x64, 0x90, 0xb1, 0x44, 0x66, 0xd4, 0x6f, 0x0c, 0xb2, 0xff, 0xf1, 0xfe, + 0x5f, 0xde, 0x3f, 0xbc, 0x75, 0x5f, 0xa4, 0x32, 0x95, 0x57, 0xbe, 0x56, 0x57, 0xfa, 0xd5, 0x17, + 0x00, 0x1f, 0x3e, 0xdc, 0x28, 0x64, 0x43, 0x9d, 0x53, 0x07, 0x10, 0xe0, 0x19, 0x7d, 0xb3, 0xfa, + 0xf5, 0x52, 0x0f, 0x87, 0x91, 0xce, 0x29, 0xb2, 0xa1, 0xb9, 0x8f, 0x33, 0x26, 0x94, 0xa3, 0x13, + 0xe0, 0xb5, 0xa2, 0x9b, 0x43, 0x6f, 0xa0, 0xb1, 0xe5, 0x82, 0x3a, 0x06, 0x01, 0x5e, 0xe7, 0x5d, + 0xd7, 0x7f, 0x7c, 0xb2, 0x3f, 0xe6, 0x82, 0x46, 0x0d, 0x59, 0xff, 0xc4, 0x85, 0xa4, 0x2c, 0x77, + 0x4c, 0x02, 0xbc, 0xbb, 0xe8, 0xe6, 0x10, 0x82, 0x46, 0xce, 0x3f, 0x31, 0xe7, 0xbe, 0x49, 0x1b, + 0xfd, 0xfa, 0x04, 0xa0, 0x51, 0x3f, 0x45, 0x5d, 0x78, 0xbf, 0x98, 0x8e, 0xa7, 0xb3, 0xd5, 0xd4, + 0xd2, 0xdc, 0x67, 0x45, 0x49, 0x9e, 0xd4, 0xf1, 0x42, 0x6c, 0x85, 0x3c, 0x0a, 0x64, 0x43, 0x63, + 0x19, 0x8e, 0x56, 0x16, 0x70, 0xdb, 0x45, 0x49, 0x1e, 0xea, 0x6a, 0xc9, 0xd9, 0x11, 0xb9, 0xd0, + 0xec, 0x0d, 0xe6, 0xe1, 0x72, 0x64, 0xe9, 0x6e, 0xa7, 0x28, 0x09, 0xac, 0x9b, 0x5e, 0xa2, 0xf8, + 0x81, 0x21, 0x02, 0x5b, 0x83, 0xd9, 0x64, 0x12, 0xce, 0xe7, 0xa3, 0xa1, 0x75, 0xe7, 0x3e, 0x2f, + 0x4a, 0xf2, 0xb4, 0xae, 0x07, 0x72, 0xb7, 0xe3, 0x4a, 0x31, 0xea, 0xb6, 0x4f, 0x5f, 0xb1, 0xf6, + 0xfd, 0x1b, 0x6e, 0x36, 0xe8, 0x3b, 0xe7, 0x0b, 0xd6, 0x7e, 0x5e, 0xb0, 0xf6, 0xb9, 0xc2, 0xe0, + 0x5c, 0x61, 0xf0, 0xa3, 0xc2, 0xe0, 0x77, 0x85, 0xc1, 0xda, 0x6c, 0xce, 0xf8, 0xfe, 0x4f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x61, 0xef, 0x92, 0x3d, 0xbc, 0x01, 0x00, 0x00, } diff --git a/snapshot/storage/proto/record.proto b/snapshot/storage/proto/record.proto index feb486017..50a462a07 100644 --- a/snapshot/storage/proto/record.proto +++ b/snapshot/storage/proto/record.proto @@ -4,16 +4,14 @@ package containerd.snapshot.v1; import "gogoproto/gogo.proto"; -// Kind defines the kind of snapshot. enum Kind { option (gogoproto.goproto_enum_prefix) = false; option (gogoproto.enum_customname) = "Kind"; - // KindActive represents an active snapshot - ACTIVE = 0 [(gogoproto.enumvalue_customname) = "KindActive"]; - - // KindCommitted represents a committed immutable snapshot - COMMITTED = 1 [(gogoproto.enumvalue_customname) = "KindCommitted"]; + UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "KindUnknown"]; + VIEW = 1 [(gogoproto.enumvalue_customname) = "KindView"]; + ACTIVE = 2 [(gogoproto.enumvalue_customname) = "KindActive"]; + COMMITTED = 3 [(gogoproto.enumvalue_customname) = "KindCommitted"]; } // Snapshot defines the storage type for a snapshot in the @@ -22,7 +20,6 @@ message Snapshot { uint64 id = 1; string parent = 2; Kind kind = 4; - bool readonly = 5; // inodes stores the number inodes in use for the snapshot. //