Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: src/platform/update_engine/filesystem_copier_action.h

Issue 1700018: AU: FilesystemCopierAction: copy bit-exactly (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: fixes for review Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H__ 5 #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H__
6 #define CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H__ 6 #define CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H__
7 7
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 #include <sys/types.h> 9 #include <sys/types.h>
10 #include <string> 10 #include <string>
11 #include <vector>
12 #include <gio/gio.h>
11 #include <glib.h> 13 #include <glib.h>
12 #include "update_engine/action.h" 14 #include "update_engine/action.h"
13 #include "update_engine/install_plan.h" 15 #include "update_engine/install_plan.h"
14 16
15 // This action will only do real work if it's a delta update. It will 17 // This action will only do real work if it's a delta update. It will
16 // format the install partition as ext3/4, copy the root filesystem into it, 18 // copy the root partition to install partition, and then terminate.
17 // and then terminate.
18
19 // Implementation notes: This action uses a helper thread, which seems to
20 // violate the design decision to only have a single thread and use
21 // asynchronous i/o. The issue is that (to the best of my knowledge),
22 // there are no linux APIs to crawl a filesystem's metadata asynchronously.
23 // The suggested way seems to be to open the raw device and parse the ext
24 // filesystem. That's not a good approach for a number of reasons:
25 // - ties us to ext filesystem
26 // - although this wouldn't happen at the time of writing, it may not handle
27 // changes to the source fs during the copy as gracefully.
28 // - requires us to have read-access to the source filesystem device, which
29 // may be a security issue.
30 //
31 // Having said this, using a helper thread is not ideal, but it's acceptable:
32 // we still honor the Action API. That is, all interaction between the action
33 // and other objects in the system (e.g. the ActionProcessor) happens on the
34 // main thread. The helper thread is fully encapsulated by the action.
35 19
36 namespace chromeos_update_engine { 20 namespace chromeos_update_engine {
37 21
38 class FilesystemCopierAction; 22 class FilesystemCopierAction;
39 23
40 template<> 24 template<>
41 class ActionTraits<FilesystemCopierAction> { 25 class ActionTraits<FilesystemCopierAction> {
42 public: 26 public:
43 // Takes the install plan as input 27 // Takes the install plan as input
44 typedef InstallPlan InputObjectType; 28 typedef InstallPlan InputObjectType;
45 // Passes the install plan as output 29 // Passes the install plan as output
46 typedef InstallPlan OutputObjectType; 30 typedef InstallPlan OutputObjectType;
47 }; 31 };
48 32
49 class FilesystemCopierAction : public Action<FilesystemCopierAction> { 33 class FilesystemCopierAction : public Action<FilesystemCopierAction> {
50 public: 34 public:
51 FilesystemCopierAction() 35 FilesystemCopierAction()
52 : thread_should_exit_(0), 36 : src_stream_(NULL),
53 is_mounted_(false), 37 dst_stream_(NULL),
54 copy_source_("/"), 38 canceller_(NULL),
55 skipped_copy_(false) {} 39 read_in_flight_(false),
40 buffer_valid_size_(0) {}
56 typedef ActionTraits<FilesystemCopierAction>::InputObjectType 41 typedef ActionTraits<FilesystemCopierAction>::InputObjectType
57 InputObjectType; 42 InputObjectType;
58 typedef ActionTraits<FilesystemCopierAction>::OutputObjectType 43 typedef ActionTraits<FilesystemCopierAction>::OutputObjectType
59 OutputObjectType; 44 OutputObjectType;
60 void PerformAction(); 45 void PerformAction();
61 void TerminateProcessing(); 46 void TerminateProcessing();
62 47
63 // Used for testing, so we can copy from somewhere other than root 48 // Used for testing, so we can copy from somewhere other than root
64 void set_copy_source(const std::string& path) { 49 void set_copy_source(const std::string& path) {
65 copy_source_ = path; 50 copy_source_ = path;
66 } 51 }
67 // Returns true if we detected that a copy was unneeded and thus skipped it.
68 bool skipped_copy() { return skipped_copy_; }
69 52
70 // Debugging/logging 53 // Debugging/logging
71 static std::string StaticType() { return "FilesystemCopierAction"; } 54 static std::string StaticType() { return "FilesystemCopierAction"; }
72 std::string Type() const { return StaticType(); } 55 std::string Type() const { return StaticType(); }
73 56
74 private: 57 private:
75 // These synchronously mount or unmount the given mountpoint 58 // Callback from glib when the copy operation is done.
76 bool Mount(const std::string& device, const std::string& mountpoint); 59 void AsyncReadyCallback(GObject *source_object, GAsyncResult *res);
77 bool Unmount(const std::string& mountpoint); 60 static void StaticAsyncReadyCallback(GObject *source_object,
61 GAsyncResult *res,
62 gpointer user_data) {
63 reinterpret_cast<FilesystemCopierAction*>(user_data)->AsyncReadyCallback(
64 source_object, res);
65 }
66
67 // Cleans up all the variables we use for async operations and tells
68 // the ActionProcessor we're done w/ success as passed in.
69 // was_cancelled should be true if TerminateProcessing() was called.
70 void Cleanup(bool success, bool was_cancelled);
71
72 // The path to copy from. If empty (the default), the source is from the
73 // passed in InstallPlan.
74 std::string copy_source_;
78 75
79 // Performs a recursive file/directory copy from copy_source_ to dest_path_. 76 // If non-NULL, these are GUnixInputStream objects for the opened
80 // Doesn't return until the copy has completed. Returns true on success 77 // source/destination partitions.
81 // or false on error. 78 GInputStream* src_stream_;
82 bool CopySynchronously(); 79 GOutputStream* dst_stream_;
80
81 // If non-NULL, the cancellable object for the in-flight async call.
82 GCancellable* canceller_;
83
84 // True if we're waiting on a read to complete; false if we're
85 // waiting on a write.
86 bool read_in_flight_;
87
88 // The buffer for storing data we read/write.
89 std::vector<char> buffer_;
83 90
84 // There are helper functions for CopySynchronously. They handle creating 91 // Number of valid elements in buffer_.
85 // various types of files. They return true on success. 92 std::vector<char>::size_type buffer_valid_size_;
86 bool CreateDirSynchronously(const std::string& new_path,
87 const struct stat& stbuf);
88 bool CopyFileSynchronously(const std::string& old_path,
89 const std::string& new_path,
90 const struct stat& stbuf);
91 bool CreateHardLinkSynchronously(const std::string& old_path,
92 const std::string& new_path);
93 // Note: Here, old_path is an existing symlink that will be copied to
94 // new_path. Thus, old_path is *not* the same as the old_path from
95 // the symlink() syscall.
96 bool CopySymlinkSynchronously(const std::string& old_path,
97 const std::string& new_path,
98 const struct stat& stbuf);
99 bool CreateNodeSynchronously(const std::string& new_path,
100 const struct stat& stbuf);
101
102 // Returns NULL on success
103 void* HelperThreadMain();
104 static void* HelperThreadMainStatic(void* data) {
105 FilesystemCopierAction* self =
106 reinterpret_cast<FilesystemCopierAction*>(data);
107 return self->HelperThreadMain();
108 }
109
110 // Joins the thread and tells the processor that we're done
111 void CollectThread();
112 // GMainLoop callback function:
113 static gboolean CollectThreadStatic(gpointer data) {
114 FilesystemCopierAction* self =
115 reinterpret_cast<FilesystemCopierAction*>(data);
116 self->CollectThread();
117 return FALSE;
118 }
119
120 pthread_t helper_thread_;
121
122 volatile gint thread_should_exit_;
123
124 static const char* kCompleteFilesystemMarker;
125
126 // Whether or not the destination device is currently mounted.
127 bool is_mounted_;
128
129 // Where the destination device is mounted.
130 std::string dest_path_;
131
132 // The path to copy from. Usually left as the default "/", but tests can
133 // change it.
134 std::string copy_source_;
135 93
136 // The install plan we're passed in via the input pipe. 94 // The install plan we're passed in via the input pipe.
137 InstallPlan install_plan_; 95 InstallPlan install_plan_;
138 96
139 // Set to true if we detected the copy was unneeded and thus we skipped it.
140 bool skipped_copy_;
141
142 DISALLOW_COPY_AND_ASSIGN(FilesystemCopierAction); 97 DISALLOW_COPY_AND_ASSIGN(FilesystemCopierAction);
143 }; 98 };
144 99
145 } // namespace chromeos_update_engine 100 } // namespace chromeos_update_engine
146 101
147 #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H__ 102 #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H__
OLDNEW
« no previous file with comments | « src/platform/update_engine/SConstruct ('k') | src/platform/update_engine/filesystem_copier_action.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698