memfs.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. // Copyright 2015 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package memfs
  15. import (
  16. "fmt"
  17. "io"
  18. "os"
  19. "syscall"
  20. "time"
  21. "golang.org/x/net/context"
  22. "github.com/jacobsa/fuse"
  23. "github.com/jacobsa/fuse/fuseops"
  24. "github.com/jacobsa/fuse/fuseutil"
  25. "github.com/jacobsa/syncutil"
  26. )
  27. type memFS struct {
  28. fuseutil.NotImplementedFileSystem
  29. // The UID and GID that every inode receives.
  30. uid uint32
  31. gid uint32
  32. /////////////////////////
  33. // Mutable state
  34. /////////////////////////
  35. mu syncutil.InvariantMutex
  36. // The collection of live inodes, indexed by ID. IDs of free inodes that may
  37. // be re-used have nil entries. No ID less than fuseops.RootInodeID is ever
  38. // used.
  39. //
  40. // All inodes are protected by the file system mutex.
  41. //
  42. // INVARIANT: For each inode in, in.CheckInvariants() does not panic.
  43. // INVARIANT: len(inodes) > fuseops.RootInodeID
  44. // INVARIANT: For all i < fuseops.RootInodeID, inodes[i] == nil
  45. // INVARIANT: inodes[fuseops.RootInodeID] != nil
  46. // INVARIANT: inodes[fuseops.RootInodeID].isDir()
  47. inodes []*inode // GUARDED_BY(mu)
  48. // A list of inode IDs within inodes available for reuse, not including the
  49. // reserved IDs less than fuseops.RootInodeID.
  50. //
  51. // INVARIANT: This is all and only indices i of 'inodes' such that i >
  52. // fuseops.RootInodeID and inodes[i] == nil
  53. freeInodes []fuseops.InodeID // GUARDED_BY(mu)
  54. }
  55. // Create a file system that stores data and metadata in memory.
  56. //
  57. // The supplied UID/GID pair will own the root inode. This file system does no
  58. // permissions checking, and should therefore be mounted with the
  59. // default_permissions option.
  60. func NewMemFS(
  61. uid uint32,
  62. gid uint32) fuse.Server {
  63. // Set up the basic struct.
  64. fs := &memFS{
  65. inodes: make([]*inode, fuseops.RootInodeID+1),
  66. uid: uid,
  67. gid: gid,
  68. }
  69. // Set up the root inode.
  70. rootAttrs := fuseops.InodeAttributes{
  71. Mode: 0700 | os.ModeDir,
  72. Uid: uid,
  73. Gid: gid,
  74. }
  75. fs.inodes[fuseops.RootInodeID] = newInode(rootAttrs)
  76. // Set up invariant checking.
  77. fs.mu = syncutil.NewInvariantMutex(fs.checkInvariants)
  78. return fuseutil.NewFileSystemServer(fs)
  79. }
  80. ////////////////////////////////////////////////////////////////////////
  81. // Helpers
  82. ////////////////////////////////////////////////////////////////////////
  83. func (fs *memFS) checkInvariants() {
  84. // Check reserved inodes.
  85. for i := 0; i < fuseops.RootInodeID; i++ {
  86. if fs.inodes[i] != nil {
  87. panic(fmt.Sprintf("Non-nil inode for ID: %v", i))
  88. }
  89. }
  90. // Check the root inode.
  91. if !fs.inodes[fuseops.RootInodeID].isDir() {
  92. panic("Expected root to be a directory.")
  93. }
  94. // Build our own list of free IDs.
  95. freeIDsEncountered := make(map[fuseops.InodeID]struct{})
  96. for i := fuseops.RootInodeID + 1; i < len(fs.inodes); i++ {
  97. inode := fs.inodes[i]
  98. if inode == nil {
  99. freeIDsEncountered[fuseops.InodeID(i)] = struct{}{}
  100. continue
  101. }
  102. }
  103. // Check fs.freeInodes.
  104. if len(fs.freeInodes) != len(freeIDsEncountered) {
  105. panic(
  106. fmt.Sprintf(
  107. "Length mismatch: %v vs. %v",
  108. len(fs.freeInodes),
  109. len(freeIDsEncountered)))
  110. }
  111. for _, id := range fs.freeInodes {
  112. if _, ok := freeIDsEncountered[id]; !ok {
  113. panic(fmt.Sprintf("Unexected free inode ID: %v", id))
  114. }
  115. }
  116. // INVARIANT: For each inode in, in.CheckInvariants() does not panic.
  117. for _, in := range fs.inodes {
  118. in.CheckInvariants()
  119. }
  120. }
  121. // Find the given inode. Panic if it doesn't exist.
  122. //
  123. // LOCKS_REQUIRED(fs.mu)
  124. func (fs *memFS) getInodeOrDie(id fuseops.InodeID) (inode *inode) {
  125. inode = fs.inodes[id]
  126. if inode == nil {
  127. panic(fmt.Sprintf("Unknown inode: %v", id))
  128. }
  129. return
  130. }
  131. // Allocate a new inode, assigning it an ID that is not in use.
  132. //
  133. // LOCKS_REQUIRED(fs.mu)
  134. func (fs *memFS) allocateInode(
  135. attrs fuseops.InodeAttributes) (id fuseops.InodeID, inode *inode) {
  136. // Create the inode.
  137. inode = newInode(attrs)
  138. // Re-use a free ID if possible. Otherwise mint a new one.
  139. numFree := len(fs.freeInodes)
  140. if numFree != 0 {
  141. id = fs.freeInodes[numFree-1]
  142. fs.freeInodes = fs.freeInodes[:numFree-1]
  143. fs.inodes[id] = inode
  144. } else {
  145. id = fuseops.InodeID(len(fs.inodes))
  146. fs.inodes = append(fs.inodes, inode)
  147. }
  148. return
  149. }
  150. // LOCKS_REQUIRED(fs.mu)
  151. func (fs *memFS) deallocateInode(id fuseops.InodeID) {
  152. fs.freeInodes = append(fs.freeInodes, id)
  153. fs.inodes[id] = nil
  154. }
  155. ////////////////////////////////////////////////////////////////////////
  156. // FileSystem methods
  157. ////////////////////////////////////////////////////////////////////////
  158. func (fs *memFS) StatFS(
  159. ctx context.Context,
  160. op *fuseops.StatFSOp) (err error) {
  161. return
  162. }
  163. func (fs *memFS) LookUpInode(
  164. ctx context.Context,
  165. op *fuseops.LookUpInodeOp) (err error) {
  166. fs.mu.Lock()
  167. defer fs.mu.Unlock()
  168. // Grab the parent directory.
  169. inode := fs.getInodeOrDie(op.Parent)
  170. // Does the directory have an entry with the given name?
  171. childID, _, ok := inode.LookUpChild(op.Name)
  172. if !ok {
  173. err = fuse.ENOENT
  174. return
  175. }
  176. // Grab the child.
  177. child := fs.getInodeOrDie(childID)
  178. // Fill in the response.
  179. op.Entry.Child = childID
  180. op.Entry.Attributes = child.attrs
  181. // We don't spontaneously mutate, so the kernel can cache as long as it wants
  182. // (since it also handles invalidation).
  183. op.Entry.AttributesExpiration = time.Now().Add(365 * 24 * time.Hour)
  184. op.Entry.EntryExpiration = op.Entry.EntryExpiration
  185. return
  186. }
  187. func (fs *memFS) GetInodeAttributes(
  188. ctx context.Context,
  189. op *fuseops.GetInodeAttributesOp) (err error) {
  190. fs.mu.Lock()
  191. defer fs.mu.Unlock()
  192. // Grab the inode.
  193. inode := fs.getInodeOrDie(op.Inode)
  194. // Fill in the response.
  195. op.Attributes = inode.attrs
  196. // We don't spontaneously mutate, so the kernel can cache as long as it wants
  197. // (since it also handles invalidation).
  198. op.AttributesExpiration = time.Now().Add(365 * 24 * time.Hour)
  199. return
  200. }
  201. func (fs *memFS) SetInodeAttributes(
  202. ctx context.Context,
  203. op *fuseops.SetInodeAttributesOp) (err error) {
  204. fs.mu.Lock()
  205. defer fs.mu.Unlock()
  206. // Grab the inode.
  207. inode := fs.getInodeOrDie(op.Inode)
  208. // Handle the request.
  209. inode.SetAttributes(op.Size, op.Mode, op.Mtime)
  210. // Fill in the response.
  211. op.Attributes = inode.attrs
  212. // We don't spontaneously mutate, so the kernel can cache as long as it wants
  213. // (since it also handles invalidation).
  214. op.AttributesExpiration = time.Now().Add(365 * 24 * time.Hour)
  215. return
  216. }
  217. func (fs *memFS) MkDir(
  218. ctx context.Context,
  219. op *fuseops.MkDirOp) (err error) {
  220. fs.mu.Lock()
  221. defer fs.mu.Unlock()
  222. // Grab the parent, which we will update shortly.
  223. parent := fs.getInodeOrDie(op.Parent)
  224. // Ensure that the name doesn't already exist, so we don't wind up with a
  225. // duplicate.
  226. _, _, exists := parent.LookUpChild(op.Name)
  227. if exists {
  228. err = fuse.EEXIST
  229. return
  230. }
  231. // Set up attributes from the child.
  232. childAttrs := fuseops.InodeAttributes{
  233. Nlink: 1,
  234. Mode: op.Mode,
  235. Uid: fs.uid,
  236. Gid: fs.gid,
  237. }
  238. // Allocate a child.
  239. childID, child := fs.allocateInode(childAttrs)
  240. // Add an entry in the parent.
  241. parent.AddChild(childID, op.Name, fuseutil.DT_Directory)
  242. // Fill in the response.
  243. op.Entry.Child = childID
  244. op.Entry.Attributes = child.attrs
  245. // We don't spontaneously mutate, so the kernel can cache as long as it wants
  246. // (since it also handles invalidation).
  247. op.Entry.AttributesExpiration = time.Now().Add(365 * 24 * time.Hour)
  248. op.Entry.EntryExpiration = op.Entry.EntryExpiration
  249. return
  250. }
  251. func (fs *memFS) MkNode(
  252. ctx context.Context,
  253. op *fuseops.MkNodeOp) (err error) {
  254. fs.mu.Lock()
  255. defer fs.mu.Unlock()
  256. op.Entry, err = fs.createFile(op.Parent, op.Name, op.Mode)
  257. return
  258. }
  259. // LOCKS_REQUIRED(fs.mu)
  260. func (fs *memFS) createFile(
  261. parentID fuseops.InodeID,
  262. name string,
  263. mode os.FileMode) (entry fuseops.ChildInodeEntry, err error) {
  264. // Grab the parent, which we will update shortly.
  265. parent := fs.getInodeOrDie(parentID)
  266. // Ensure that the name doesn't already exist, so we don't wind up with a
  267. // duplicate.
  268. _, _, exists := parent.LookUpChild(name)
  269. if exists {
  270. err = fuse.EEXIST
  271. return
  272. }
  273. // Set up attributes for the child.
  274. now := time.Now()
  275. childAttrs := fuseops.InodeAttributes{
  276. Nlink: 1,
  277. Mode: mode,
  278. Atime: now,
  279. Mtime: now,
  280. Ctime: now,
  281. Crtime: now,
  282. Uid: fs.uid,
  283. Gid: fs.gid,
  284. }
  285. // Allocate a child.
  286. childID, child := fs.allocateInode(childAttrs)
  287. // Add an entry in the parent.
  288. parent.AddChild(childID, name, fuseutil.DT_File)
  289. // Fill in the response entry.
  290. entry.Child = childID
  291. entry.Attributes = child.attrs
  292. // We don't spontaneously mutate, so the kernel can cache as long as it wants
  293. // (since it also handles invalidation).
  294. entry.AttributesExpiration = time.Now().Add(365 * 24 * time.Hour)
  295. entry.EntryExpiration = entry.AttributesExpiration
  296. return
  297. }
  298. func (fs *memFS) CreateFile(
  299. ctx context.Context,
  300. op *fuseops.CreateFileOp) (err error) {
  301. fs.mu.Lock()
  302. defer fs.mu.Unlock()
  303. op.Entry, err = fs.createFile(op.Parent, op.Name, op.Mode)
  304. return
  305. }
  306. func (fs *memFS) CreateSymlink(
  307. ctx context.Context,
  308. op *fuseops.CreateSymlinkOp) (err error) {
  309. fs.mu.Lock()
  310. defer fs.mu.Unlock()
  311. // Grab the parent, which we will update shortly.
  312. parent := fs.getInodeOrDie(op.Parent)
  313. // Ensure that the name doesn't already exist, so we don't wind up with a
  314. // duplicate.
  315. _, _, exists := parent.LookUpChild(op.Name)
  316. if exists {
  317. err = fuse.EEXIST
  318. return
  319. }
  320. // Set up attributes from the child.
  321. now := time.Now()
  322. childAttrs := fuseops.InodeAttributes{
  323. Nlink: 1,
  324. Mode: 0444 | os.ModeSymlink,
  325. Atime: now,
  326. Mtime: now,
  327. Ctime: now,
  328. Crtime: now,
  329. Uid: fs.uid,
  330. Gid: fs.gid,
  331. }
  332. // Allocate a child.
  333. childID, child := fs.allocateInode(childAttrs)
  334. // Set up its target.
  335. child.target = op.Target
  336. // Add an entry in the parent.
  337. parent.AddChild(childID, op.Name, fuseutil.DT_Link)
  338. // Fill in the response entry.
  339. op.Entry.Child = childID
  340. op.Entry.Attributes = child.attrs
  341. // We don't spontaneously mutate, so the kernel can cache as long as it wants
  342. // (since it also handles invalidation).
  343. op.Entry.AttributesExpiration = time.Now().Add(365 * 24 * time.Hour)
  344. op.Entry.EntryExpiration = op.Entry.EntryExpiration
  345. return
  346. }
  347. func (fs *memFS) Rename(
  348. ctx context.Context,
  349. op *fuseops.RenameOp) (err error) {
  350. fs.mu.Lock()
  351. defer fs.mu.Unlock()
  352. // Ask the old parent for the child's inode ID and type.
  353. oldParent := fs.getInodeOrDie(op.OldParent)
  354. childID, childType, ok := oldParent.LookUpChild(op.OldName)
  355. if !ok {
  356. err = fuse.ENOENT
  357. return
  358. }
  359. // If the new name exists already in the new parent, make sure it's not a
  360. // non-empty directory, then delete it.
  361. newParent := fs.getInodeOrDie(op.NewParent)
  362. existingID, _, ok := newParent.LookUpChild(op.NewName)
  363. if ok {
  364. existing := fs.getInodeOrDie(existingID)
  365. var buf [4096]byte
  366. if existing.isDir() && existing.ReadDir(buf[:], 0) > 0 {
  367. err = fuse.ENOTEMPTY
  368. return
  369. }
  370. newParent.RemoveChild(op.NewName)
  371. }
  372. // Link the new name.
  373. newParent.AddChild(
  374. childID,
  375. op.NewName,
  376. childType)
  377. // Finally, remove the old name from the old parent.
  378. oldParent.RemoveChild(op.OldName)
  379. return
  380. }
  381. func (fs *memFS) RmDir(
  382. ctx context.Context,
  383. op *fuseops.RmDirOp) (err error) {
  384. fs.mu.Lock()
  385. defer fs.mu.Unlock()
  386. // Grab the parent, which we will update shortly.
  387. parent := fs.getInodeOrDie(op.Parent)
  388. // Find the child within the parent.
  389. childID, _, ok := parent.LookUpChild(op.Name)
  390. if !ok {
  391. err = fuse.ENOENT
  392. return
  393. }
  394. // Grab the child.
  395. child := fs.getInodeOrDie(childID)
  396. // Make sure the child is empty.
  397. if child.Len() != 0 {
  398. err = fuse.ENOTEMPTY
  399. return
  400. }
  401. // Remove the entry within the parent.
  402. parent.RemoveChild(op.Name)
  403. // Mark the child as unlinked.
  404. child.attrs.Nlink--
  405. return
  406. }
  407. func (fs *memFS) Unlink(
  408. ctx context.Context,
  409. op *fuseops.UnlinkOp) (err error) {
  410. fs.mu.Lock()
  411. defer fs.mu.Unlock()
  412. // Grab the parent, which we will update shortly.
  413. parent := fs.getInodeOrDie(op.Parent)
  414. // Find the child within the parent.
  415. childID, _, ok := parent.LookUpChild(op.Name)
  416. if !ok {
  417. err = fuse.ENOENT
  418. return
  419. }
  420. // Grab the child.
  421. child := fs.getInodeOrDie(childID)
  422. // Remove the entry within the parent.
  423. parent.RemoveChild(op.Name)
  424. // Mark the child as unlinked.
  425. child.attrs.Nlink--
  426. return
  427. }
  428. func (fs *memFS) OpenDir(
  429. ctx context.Context,
  430. op *fuseops.OpenDirOp) (err error) {
  431. fs.mu.Lock()
  432. defer fs.mu.Unlock()
  433. // We don't mutate spontaneosuly, so if the VFS layer has asked for an
  434. // inode that doesn't exist, something screwed up earlier (a lookup, a
  435. // cache invalidation, etc.).
  436. inode := fs.getInodeOrDie(op.Inode)
  437. if !inode.isDir() {
  438. panic("Found non-dir.")
  439. }
  440. return
  441. }
  442. func (fs *memFS) ReadDir(
  443. ctx context.Context,
  444. op *fuseops.ReadDirOp) (err error) {
  445. fs.mu.Lock()
  446. defer fs.mu.Unlock()
  447. // Grab the directory.
  448. inode := fs.getInodeOrDie(op.Inode)
  449. // Serve the request.
  450. op.BytesRead = inode.ReadDir(op.Dst, int(op.Offset))
  451. return
  452. }
  453. func (fs *memFS) OpenFile(
  454. ctx context.Context,
  455. op *fuseops.OpenFileOp) (err error) {
  456. fs.mu.Lock()
  457. defer fs.mu.Unlock()
  458. // We don't mutate spontaneosuly, so if the VFS layer has asked for an
  459. // inode that doesn't exist, something screwed up earlier (a lookup, a
  460. // cache invalidation, etc.).
  461. inode := fs.getInodeOrDie(op.Inode)
  462. if !inode.isFile() {
  463. panic("Found non-file.")
  464. }
  465. return
  466. }
  467. func (fs *memFS) ReadFile(
  468. ctx context.Context,
  469. op *fuseops.ReadFileOp) (err error) {
  470. fs.mu.Lock()
  471. defer fs.mu.Unlock()
  472. // Find the inode in question.
  473. inode := fs.getInodeOrDie(op.Inode)
  474. // Serve the request.
  475. op.BytesRead, err = inode.ReadAt(op.Dst, op.Offset)
  476. // Don't return EOF errors; we just indicate EOF to fuse using a short read.
  477. if err == io.EOF {
  478. err = nil
  479. }
  480. return
  481. }
  482. func (fs *memFS) WriteFile(
  483. ctx context.Context,
  484. op *fuseops.WriteFileOp) (err error) {
  485. fs.mu.Lock()
  486. defer fs.mu.Unlock()
  487. // Find the inode in question.
  488. inode := fs.getInodeOrDie(op.Inode)
  489. // Serve the request.
  490. _, err = inode.WriteAt(op.Data, op.Offset)
  491. return
  492. }
  493. func (fs *memFS) ReadSymlink(
  494. ctx context.Context,
  495. op *fuseops.ReadSymlinkOp) (err error) {
  496. fs.mu.Lock()
  497. defer fs.mu.Unlock()
  498. // Find the inode in question.
  499. inode := fs.getInodeOrDie(op.Inode)
  500. // Serve the request.
  501. op.Target = inode.target
  502. return
  503. }
  504. func (fs *memFS) GetXattr(ctx context.Context,
  505. op *fuseops.GetXattrOp) (err error) {
  506. fs.mu.Lock()
  507. defer fs.mu.Unlock()
  508. inode := fs.getInodeOrDie(op.Inode)
  509. if value, ok := inode.xattrs[op.Name]; ok {
  510. op.BytesRead = len(value)
  511. if len(op.Dst) >= len(value) {
  512. copy(op.Dst, value)
  513. } else {
  514. err = syscall.ERANGE
  515. }
  516. } else {
  517. err = fuse.ENOATTR
  518. }
  519. return
  520. }
  521. func (fs *memFS) ListXattr(ctx context.Context,
  522. op *fuseops.ListXattrOp) (err error) {
  523. fs.mu.Lock()
  524. defer fs.mu.Unlock()
  525. inode := fs.getInodeOrDie(op.Inode)
  526. dst := op.Dst[:]
  527. for key := range inode.xattrs {
  528. keyLen := len(key) + 1
  529. if err == nil && len(dst) >= keyLen {
  530. copy(dst, key)
  531. dst = dst[keyLen:]
  532. } else {
  533. err = syscall.ERANGE
  534. }
  535. op.BytesRead += keyLen
  536. }
  537. return
  538. }
  539. func (fs *memFS) RemoveXattr(ctx context.Context,
  540. op *fuseops.RemoveXattrOp) (err error) {
  541. fs.mu.Lock()
  542. defer fs.mu.Unlock()
  543. inode := fs.getInodeOrDie(op.Inode)
  544. if _, ok := inode.xattrs[op.Name]; ok {
  545. delete(inode.xattrs, op.Name)
  546. } else {
  547. err = fuse.ENOATTR
  548. }
  549. return
  550. }
  551. func (fs *memFS) SetXattr(ctx context.Context,
  552. op *fuseops.SetXattrOp) (err error) {
  553. fs.mu.Lock()
  554. defer fs.mu.Unlock()
  555. inode := fs.getInodeOrDie(op.Inode)
  556. _, ok := inode.xattrs[op.Name]
  557. switch op.Flags {
  558. case 0x1:
  559. if ok {
  560. err = fuse.EEXIST
  561. }
  562. case 0x2:
  563. if !ok {
  564. err = fuse.ENOATTR
  565. }
  566. }
  567. if err == nil {
  568. value := make([]byte, len(op.Value))
  569. copy(value, op.Value)
  570. inode.xattrs[op.Name] = value
  571. }
  572. return
  573. }