| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS 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 #include "update_engine/extent_mapper.h" | 5 #include "update_engine/extent_mapper.h" | 
| 6 | 6 | 
| 7 #include <sys/ioctl.h> | 7 #include <sys/ioctl.h> | 
| 8 #include <sys/types.h> | 8 #include <sys/types.h> | 
| 9 #include <sys/stat.h> | 9 #include <sys/stat.h> | 
| 10 | 10 | 
| 11 #include <assert.h> | 11 #include <assert.h> | 
| 12 #include <errno.h> | 12 #include <errno.h> | 
| 13 #include <fcntl.h> | 13 #include <fcntl.h> | 
| 14 #include <stdio.h> | 14 #include <stdio.h> | 
| 15 #include <string.h> | 15 #include <string.h> | 
| 16 | 16 | 
| 17 #include <linux/fs.h> | 17 #include <linux/fs.h> | 
| 18 | 18 | 
|  | 19 #include "update_engine/graph_types.h" | 
|  | 20 #include "update_engine/graph_utils.h" | 
| 19 #include "update_engine/utils.h" | 21 #include "update_engine/utils.h" | 
| 20 | 22 | 
| 21 using std::string; | 23 using std::string; | 
| 22 using std::vector; | 24 using std::vector; | 
| 23 | 25 | 
| 24 namespace chromeos_update_engine { | 26 namespace chromeos_update_engine { | 
| 25 | 27 | 
| 26 namespace extent_mapper { | 28 namespace extent_mapper { | 
| 27 | 29 | 
| 28 namespace { | 30 namespace { | 
| 29 const int kBlockSize = 4096; | 31 const int kBlockSize = 4096; | 
| 30 } | 32 } | 
| 31 | 33 | 
| 32 bool ExtentsForFileFibmap(const std::string& path, std::vector<Extent>* out) { | 34 bool ExtentsForFileFibmap(const std::string& path, std::vector<Extent>* out) { | 
| 33   CHECK(out); | 35   CHECK(out); | 
| 34   // TODO(adlr): verify path is a file |  | 
| 35   struct stat stbuf; | 36   struct stat stbuf; | 
| 36   int rc = stat(path.c_str(), &stbuf); | 37   int rc = stat(path.c_str(), &stbuf); | 
| 37   TEST_AND_RETURN_FALSE_ERRNO(rc == 0); | 38   TEST_AND_RETURN_FALSE_ERRNO(rc == 0); | 
| 38   TEST_AND_RETURN_FALSE(S_ISREG(stbuf.st_mode)); | 39   TEST_AND_RETURN_FALSE(S_ISREG(stbuf.st_mode)); | 
| 39 | 40 | 
| 40   int fd = open(path.c_str(), O_RDONLY, 0); | 41   int fd = open(path.c_str(), O_RDONLY, 0); | 
| 41   TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); | 42   TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); | 
| 42   ScopedFdCloser fd_closer(&fd); | 43   ScopedFdCloser fd_closer(&fd); | 
| 43 | 44 | 
| 44   // Get file size in blocks | 45   // Get file size in blocks | 
| 45   rc = fstat(fd, &stbuf); | 46   rc = fstat(fd, &stbuf); | 
| 46   if (rc < 0) { | 47   if (rc < 0) { | 
| 47     perror("fstat"); | 48     perror("fstat"); | 
| 48     return false; | 49     return false; | 
| 49   } | 50   } | 
| 50   const int block_count = (stbuf.st_size + kBlockSize - 1) / kBlockSize; | 51   const int block_count = (stbuf.st_size + kBlockSize - 1) / kBlockSize; | 
| 51   Extent current; | 52   Extent current; | 
| 52   current.set_start_block(0); | 53   current.set_start_block(0); | 
| 53   current.set_num_blocks(0); | 54   current.set_num_blocks(0); | 
| 54 | 55 | 
| 55   for (int i = 0; i < block_count; i++) { | 56   for (int i = 0; i < block_count; i++) { | 
| 56     unsigned int block = i; | 57     unsigned int block32 = i; | 
| 57     rc = ioctl(fd, FIBMAP, &block); | 58     rc = ioctl(fd, FIBMAP, &block32); | 
| 58     TEST_AND_RETURN_FALSE_ERRNO(rc == 0); | 59     TEST_AND_RETURN_FALSE_ERRNO(rc == 0); | 
| 59 | 60 | 
| 60     // Add next block to extents | 61     const uint64 block = (block32 == 0 ? kSparseHole : block32); | 
| 61     if (current.num_blocks() == 0) { | 62 | 
| 62       // We're starting a new extent | 63     graph_utils::AppendBlockToExtents(out, block); | 
| 63       current.set_start_block(block); |  | 
| 64       current.set_num_blocks(1); |  | 
| 65       continue; |  | 
| 66     } |  | 
| 67     if ((current.start_block() + current.num_blocks()) == block) { |  | 
| 68       // We're continuing the last extent |  | 
| 69       current.set_num_blocks(current.num_blocks() + 1); |  | 
| 70       continue; |  | 
| 71     } |  | 
| 72     // We're starting a new extent and keeping the current one |  | 
| 73     out->push_back(current); |  | 
| 74     current.set_start_block(block); |  | 
| 75     current.set_num_blocks(1); |  | 
| 76     continue; |  | 
| 77   } | 64   } | 
| 78 |  | 
| 79   if (current.num_blocks() > 0) |  | 
| 80     out->push_back(current); |  | 
| 81 |  | 
| 82   return true; | 65   return true; | 
| 83 } | 66 } | 
| 84 | 67 | 
|  | 68 bool GetFilesystemBlockSize(const std::string& path, uint32* out_blocksize) { | 
|  | 69   int fd = open(path.c_str(), O_RDONLY, 0); | 
|  | 70   TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); | 
|  | 71   ScopedFdCloser fd_closer(&fd); | 
|  | 72   int rc = ioctl(fd, FIGETBSZ, out_blocksize); | 
|  | 73   TEST_AND_RETURN_FALSE_ERRNO(rc != -1); | 
|  | 74   return true; | 
|  | 75 } | 
|  | 76 | 
| 85 }  // namespace extent_mapper | 77 }  // namespace extent_mapper | 
| 86 | 78 | 
| 87 }  // namespace chromeos_update_engine | 79 }  // namespace chromeos_update_engine | 
| OLD | NEW | 
|---|