flush_fs_test.go 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  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 flushfs_test
  15. import (
  16. "bufio"
  17. "encoding/hex"
  18. "fmt"
  19. "io"
  20. "io/ioutil"
  21. "os"
  22. "path"
  23. "runtime"
  24. "syscall"
  25. "testing"
  26. "time"
  27. "unsafe"
  28. "golang.org/x/sys/unix"
  29. "github.com/jacobsa/fuse/fsutil"
  30. "github.com/jacobsa/fuse/fusetesting"
  31. "github.com/jacobsa/fuse/samples"
  32. . "github.com/jacobsa/oglematchers"
  33. . "github.com/jacobsa/ogletest"
  34. )
  35. func TestFlushFS(t *testing.T) { RunTests(t) }
  36. ////////////////////////////////////////////////////////////////////////
  37. // Boilerplate
  38. ////////////////////////////////////////////////////////////////////////
  39. type flushFSTest struct {
  40. samples.SubprocessTest
  41. // Files to which mount_sample is writing reported flushes and fsyncs.
  42. flushes *os.File
  43. fsyncs *os.File
  44. // File handles that are closed in TearDown if non-nil.
  45. f1 *os.File
  46. f2 *os.File
  47. }
  48. func (t *flushFSTest) setUp(
  49. ti *TestInfo,
  50. flushErr syscall.Errno,
  51. fsyncErr syscall.Errno,
  52. readOnly bool) {
  53. var err error
  54. // Set up files to receive flush and fsync reports.
  55. t.flushes, err = fsutil.AnonymousFile("")
  56. AssertEq(nil, err)
  57. t.fsyncs, err = fsutil.AnonymousFile("")
  58. AssertEq(nil, err)
  59. // Set up test config.
  60. t.MountType = "flushfs"
  61. t.MountFlags = []string{
  62. "--flushfs.flush_error",
  63. fmt.Sprintf("%d", int(flushErr)),
  64. "--flushfs.fsync_error",
  65. fmt.Sprintf("%d", int(fsyncErr)),
  66. }
  67. if readOnly {
  68. t.MountFlags = append(t.MountFlags, "--read_only")
  69. }
  70. t.MountFiles = map[string]*os.File{
  71. "flushfs.flushes_file": t.flushes,
  72. "flushfs.fsyncs_file": t.fsyncs,
  73. }
  74. t.SubprocessTest.SetUp(ti)
  75. }
  76. func (t *flushFSTest) TearDown() {
  77. // Unlink reporting files.
  78. os.Remove(t.flushes.Name())
  79. os.Remove(t.fsyncs.Name())
  80. // Close reporting files.
  81. t.flushes.Close()
  82. t.fsyncs.Close()
  83. // Close test files if non-nil.
  84. if t.f1 != nil {
  85. ExpectEq(nil, t.f1.Close())
  86. }
  87. if t.f2 != nil {
  88. ExpectEq(nil, t.f2.Close())
  89. }
  90. // Finish tearing down.
  91. t.SubprocessTest.TearDown()
  92. }
  93. ////////////////////////////////////////////////////////////////////////
  94. // Helpers
  95. ////////////////////////////////////////////////////////////////////////
  96. var isDarwin = runtime.GOOS == "darwin"
  97. func readReports(f *os.File) (reports []string, err error) {
  98. // Seek the file to the start.
  99. _, err = f.Seek(0, 0)
  100. if err != nil {
  101. err = fmt.Errorf("Seek: %v", err)
  102. return
  103. }
  104. // We expect reports to end in a newline (including the final one).
  105. reader := bufio.NewReader(f)
  106. for {
  107. var record []byte
  108. record, err = reader.ReadBytes('\n')
  109. if err == io.EOF {
  110. if len(record) != 0 {
  111. err = fmt.Errorf("Unexpected record:\n%s", hex.Dump(record))
  112. return
  113. }
  114. err = nil
  115. return
  116. }
  117. if err != nil {
  118. err = fmt.Errorf("ReadBytes: %v", err)
  119. return
  120. }
  121. // Strip the newline.
  122. reports = append(reports, string(record[:len(record)-1]))
  123. }
  124. }
  125. // Return a copy of the current contents of t.flushes.
  126. func (t *flushFSTest) getFlushes() (p []string) {
  127. var err error
  128. if p, err = readReports(t.flushes); err != nil {
  129. panic(err)
  130. }
  131. return
  132. }
  133. // Return a copy of the current contents of t.fsyncs.
  134. func (t *flushFSTest) getFsyncs() (p []string) {
  135. var err error
  136. if p, err = readReports(t.fsyncs); err != nil {
  137. panic(err)
  138. }
  139. return
  140. }
  141. // Like syscall.Dup2, but correctly annotates the syscall as blocking. See here
  142. // for more info: https://github.com/golang/go/issues/10202
  143. func dup2(oldfd int, newfd int) (err error) {
  144. _, _, e1 := syscall.Syscall(
  145. syscall.SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
  146. if e1 != 0 {
  147. err = e1
  148. }
  149. return
  150. }
  151. // Call msync(2) with the MS_SYNC flag on a slice previously returned by
  152. // mmap(2).
  153. func msync(p []byte) (err error) {
  154. _, _, errno := unix.Syscall(
  155. unix.SYS_MSYNC,
  156. uintptr(unsafe.Pointer(&p[0])),
  157. uintptr(len(p)),
  158. unix.MS_SYNC)
  159. if errno != 0 {
  160. err = errno
  161. return
  162. }
  163. return
  164. }
  165. ////////////////////////////////////////////////////////////////////////
  166. // No errors
  167. ////////////////////////////////////////////////////////////////////////
  168. type NoErrorsTest struct {
  169. flushFSTest
  170. }
  171. func init() { RegisterTestSuite(&NoErrorsTest{}) }
  172. func (t *NoErrorsTest) SetUp(ti *TestInfo) {
  173. const noErr = 0
  174. t.flushFSTest.setUp(ti, noErr, noErr, false)
  175. }
  176. func (t *NoErrorsTest) Close_ReadWrite() {
  177. var n int
  178. var off int64
  179. var err error
  180. buf := make([]byte, 1024)
  181. // Open the file.
  182. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  183. AssertEq(nil, err)
  184. // Write some contents to the file.
  185. n, err = t.f1.Write([]byte("taco"))
  186. AssertEq(nil, err)
  187. AssertEq(4, n)
  188. // Seek and read them back.
  189. off, err = t.f1.Seek(0, 0)
  190. AssertEq(nil, err)
  191. AssertEq(0, off)
  192. n, err = t.f1.Read(buf)
  193. AssertThat(err, AnyOf(nil, io.EOF))
  194. AssertEq("taco", string(buf[:n]))
  195. // At this point, no flushes or fsyncs should have happened.
  196. AssertThat(t.getFlushes(), ElementsAre())
  197. AssertThat(t.getFsyncs(), ElementsAre())
  198. // Close the file.
  199. err = t.f1.Close()
  200. t.f1 = nil
  201. AssertEq(nil, err)
  202. // Now we should have received the flush operation (but still no fsync).
  203. ExpectThat(t.getFlushes(), ElementsAre("taco"))
  204. ExpectThat(t.getFsyncs(), ElementsAre())
  205. }
  206. func (t *NoErrorsTest) Close_ReadOnly() {
  207. var err error
  208. // Open the file.
  209. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDONLY, 0)
  210. AssertEq(nil, err)
  211. // At this point, no flushes or fsyncs should have happened.
  212. AssertThat(t.getFlushes(), ElementsAre())
  213. AssertThat(t.getFsyncs(), ElementsAre())
  214. // Close the file.
  215. err = t.f1.Close()
  216. t.f1 = nil
  217. AssertEq(nil, err)
  218. // Now we should have received the flush operation (but still no fsync).
  219. ExpectThat(t.getFlushes(), ElementsAre(""))
  220. ExpectThat(t.getFsyncs(), ElementsAre())
  221. }
  222. func (t *NoErrorsTest) Close_WriteOnly() {
  223. var n int
  224. var err error
  225. // Open the file.
  226. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  227. AssertEq(nil, err)
  228. // Write some contents to the file.
  229. n, err = t.f1.Write([]byte("taco"))
  230. AssertEq(nil, err)
  231. AssertEq(4, n)
  232. // At this point, no flushes or fsyncs should have happened.
  233. AssertThat(t.getFlushes(), ElementsAre())
  234. AssertThat(t.getFsyncs(), ElementsAre())
  235. // Close the file.
  236. err = t.f1.Close()
  237. t.f1 = nil
  238. AssertEq(nil, err)
  239. // Now we should have received the flush operation (but still no fsync).
  240. ExpectThat(t.getFlushes(), ElementsAre("taco"))
  241. ExpectThat(t.getFsyncs(), ElementsAre())
  242. }
  243. func (t *NoErrorsTest) Close_MultipleTimes_NonOverlappingFileHandles() {
  244. var n int
  245. var err error
  246. // Open the file.
  247. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  248. AssertEq(nil, err)
  249. // Write some contents to the file.
  250. n, err = t.f1.Write([]byte("taco"))
  251. AssertEq(nil, err)
  252. AssertEq(4, n)
  253. // At this point, no flushes or fsyncs should have happened.
  254. AssertThat(t.getFlushes(), ElementsAre())
  255. AssertThat(t.getFsyncs(), ElementsAre())
  256. // Close the file.
  257. err = t.f1.Close()
  258. t.f1 = nil
  259. AssertEq(nil, err)
  260. // Now we should have received the flush operation (but still no fsync).
  261. AssertThat(t.getFlushes(), ElementsAre("taco"))
  262. AssertThat(t.getFsyncs(), ElementsAre())
  263. // Open the file again.
  264. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  265. AssertEq(nil, err)
  266. // Write again; expect no further flushes.
  267. n, err = t.f1.Write([]byte("p"))
  268. AssertEq(nil, err)
  269. AssertEq(1, n)
  270. AssertThat(t.getFlushes(), ElementsAre("taco"))
  271. AssertThat(t.getFsyncs(), ElementsAre())
  272. // Close the file. Now the new contents should be flushed.
  273. err = t.f1.Close()
  274. t.f1 = nil
  275. AssertEq(nil, err)
  276. AssertThat(t.getFlushes(), ElementsAre("taco", "paco"))
  277. AssertThat(t.getFsyncs(), ElementsAre())
  278. }
  279. func (t *NoErrorsTest) Close_MultipleTimes_OverlappingFileHandles() {
  280. var n int
  281. var err error
  282. // Open the file with two handles.
  283. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  284. AssertEq(nil, err)
  285. t.f2, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  286. AssertEq(nil, err)
  287. // Write some contents with each handle.
  288. n, err = t.f1.Write([]byte("taco"))
  289. AssertEq(nil, err)
  290. AssertEq(4, n)
  291. n, err = t.f2.Write([]byte("p"))
  292. AssertEq(nil, err)
  293. AssertEq(1, n)
  294. // At this point, no flushes or fsyncs should have happened.
  295. AssertThat(t.getFlushes(), ElementsAre())
  296. AssertThat(t.getFsyncs(), ElementsAre())
  297. // Close one handle. The current contents should be flushed.
  298. err = t.f1.Close()
  299. t.f1 = nil
  300. AssertEq(nil, err)
  301. AssertThat(t.getFlushes(), ElementsAre("paco"))
  302. AssertThat(t.getFsyncs(), ElementsAre())
  303. // Write some more contents via the other handle. Again, no further flushes.
  304. n, err = t.f2.Write([]byte("orp"))
  305. AssertEq(nil, err)
  306. AssertEq(3, n)
  307. AssertThat(t.getFlushes(), ElementsAre("paco"))
  308. AssertThat(t.getFsyncs(), ElementsAre())
  309. // Close the handle. Now the new contents should be flushed.
  310. err = t.f2.Close()
  311. t.f2 = nil
  312. AssertEq(nil, err)
  313. AssertThat(t.getFlushes(), ElementsAre("paco", "porp"))
  314. AssertThat(t.getFsyncs(), ElementsAre())
  315. }
  316. func (t *NoErrorsTest) Fsync() {
  317. var n int
  318. var err error
  319. // Open the file.
  320. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  321. AssertEq(nil, err)
  322. // Write some contents to the file.
  323. n, err = t.f1.Write([]byte("taco"))
  324. AssertEq(nil, err)
  325. AssertEq(4, n)
  326. AssertThat(t.getFlushes(), ElementsAre())
  327. AssertThat(t.getFsyncs(), ElementsAre())
  328. // Fsync.
  329. err = t.f1.Sync()
  330. AssertEq(nil, err)
  331. AssertThat(t.getFlushes(), ElementsAre())
  332. AssertThat(t.getFsyncs(), ElementsAre("taco"))
  333. // Write some more contents.
  334. n, err = t.f1.Write([]byte("s"))
  335. AssertEq(nil, err)
  336. AssertEq(1, n)
  337. AssertThat(t.getFlushes(), ElementsAre())
  338. AssertThat(t.getFsyncs(), ElementsAre("taco"))
  339. // Fsync.
  340. err = t.f1.Sync()
  341. AssertEq(nil, err)
  342. AssertThat(t.getFlushes(), ElementsAre())
  343. AssertThat(t.getFsyncs(), ElementsAre("taco", "tacos"))
  344. }
  345. func (t *NoErrorsTest) Fdatasync() {
  346. var n int
  347. var err error
  348. if !fsutil.FdatasyncSupported {
  349. return
  350. }
  351. // Open the file.
  352. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  353. AssertEq(nil, err)
  354. // Write some contents to the file.
  355. n, err = t.f1.Write([]byte("taco"))
  356. AssertEq(nil, err)
  357. AssertEq(4, n)
  358. AssertThat(t.getFlushes(), ElementsAre())
  359. AssertThat(t.getFsyncs(), ElementsAre())
  360. // Fdatasync.
  361. err = fsutil.Fdatasync(t.f1)
  362. AssertEq(nil, err)
  363. AssertThat(t.getFlushes(), ElementsAre())
  364. AssertThat(t.getFsyncs(), ElementsAre("taco"))
  365. // Write some more contents.
  366. n, err = t.f1.Write([]byte("s"))
  367. AssertEq(nil, err)
  368. AssertEq(1, n)
  369. AssertThat(t.getFlushes(), ElementsAre())
  370. AssertThat(t.getFsyncs(), ElementsAre("taco"))
  371. // Fdatasync.
  372. err = fsutil.Fdatasync(t.f1)
  373. AssertEq(nil, err)
  374. AssertThat(t.getFlushes(), ElementsAre())
  375. AssertThat(t.getFsyncs(), ElementsAre("taco", "tacos"))
  376. }
  377. func (t *NoErrorsTest) Dup() {
  378. var n int
  379. var err error
  380. var expectedFlushes []interface{}
  381. // Open the file.
  382. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  383. AssertEq(nil, err)
  384. fd1 := t.f1.Fd()
  385. // Use dup(2) to get another copy.
  386. fd2, err := syscall.Dup(int(fd1))
  387. AssertEq(nil, err)
  388. t.f2 = os.NewFile(uintptr(fd2), t.f1.Name())
  389. // Write some contents with each handle.
  390. n, err = t.f1.Write([]byte("taco"))
  391. AssertEq(nil, err)
  392. AssertEq(4, n)
  393. n, err = t.f2.Write([]byte("s"))
  394. AssertEq(nil, err)
  395. AssertEq(1, n)
  396. // At this point, no flushes or fsyncs should have happened.
  397. AssertThat(t.getFlushes(), ElementsAre())
  398. AssertThat(t.getFsyncs(), ElementsAre())
  399. // Close one handle. On Linux the current contents should be flushed. On OS
  400. // X, where the semantics of handles are different, they apparently are not.
  401. // (Cf. https://github.com/osxfuse/osxfuse/issues/199)
  402. err = t.f1.Close()
  403. t.f1 = nil
  404. AssertEq(nil, err)
  405. if !isDarwin {
  406. expectedFlushes = append(expectedFlushes, "tacos")
  407. }
  408. AssertThat(t.getFlushes(), ElementsAre(expectedFlushes...))
  409. AssertThat(t.getFsyncs(), ElementsAre())
  410. // Write some more contents via the other handle. Again, no further flushes.
  411. n, err = t.f2.Write([]byte("!"))
  412. AssertEq(nil, err)
  413. AssertEq(1, n)
  414. AssertThat(t.getFlushes(), ElementsAre(expectedFlushes...))
  415. AssertThat(t.getFsyncs(), ElementsAre())
  416. // Close the handle. Now the new contents should be flushed.
  417. err = t.f2.Close()
  418. t.f2 = nil
  419. AssertEq(nil, err)
  420. expectedFlushes = append(expectedFlushes, "tacos!")
  421. ExpectThat(t.getFlushes(), ElementsAre(expectedFlushes...))
  422. ExpectThat(t.getFsyncs(), ElementsAre())
  423. }
  424. func (t *NoErrorsTest) Dup2() {
  425. var n int
  426. var err error
  427. // Open the file.
  428. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  429. AssertEq(nil, err)
  430. // Write some contents to the file.
  431. n, err = t.f1.Write([]byte("taco"))
  432. AssertEq(nil, err)
  433. AssertEq(4, n)
  434. // Create some anonymous temporary file.
  435. t.f2, err = fsutil.AnonymousFile("")
  436. AssertEq(nil, err)
  437. // Duplicate the temporary file descriptor on top of the file from our file
  438. // system. We should see a flush.
  439. err = dup2(int(t.f2.Fd()), int(t.f1.Fd()))
  440. ExpectEq(nil, err)
  441. ExpectThat(t.getFlushes(), ElementsAre("taco"))
  442. ExpectThat(t.getFsyncs(), ElementsAre())
  443. }
  444. func (t *NoErrorsTest) Mmap_NoMsync_MunmapBeforeClose() {
  445. var n int
  446. var err error
  447. // Open the file.
  448. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  449. AssertEq(nil, err)
  450. // Write some contents to the file.
  451. n, err = t.f1.Write([]byte("taco"))
  452. AssertEq(nil, err)
  453. AssertEq(4, n)
  454. // mmap the file.
  455. data, err := syscall.Mmap(
  456. int(t.f1.Fd()), 0, 4,
  457. syscall.PROT_READ|syscall.PROT_WRITE,
  458. syscall.MAP_SHARED)
  459. AssertEq(nil, err)
  460. defer syscall.Munmap(data)
  461. AssertEq("taco", string(data))
  462. // Modify the contents.
  463. data[0] = 'p'
  464. // Unmap.
  465. err = syscall.Munmap(data)
  466. AssertEq(nil, err)
  467. // munmap does not cause a flush.
  468. ExpectThat(t.getFlushes(), ElementsAre())
  469. ExpectThat(t.getFsyncs(), ElementsAre())
  470. // Close the file. We should see a flush with up to date contents.
  471. err = t.f1.Close()
  472. t.f1 = nil
  473. AssertEq(nil, err)
  474. ExpectThat(t.getFlushes(), ElementsAre("paco"))
  475. ExpectThat(t.getFsyncs(), ElementsAre())
  476. }
  477. func (t *NoErrorsTest) Mmap_NoMsync_CloseBeforeMunmap() {
  478. var n int
  479. var err error
  480. // Open the file.
  481. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  482. AssertEq(nil, err)
  483. // Write some contents to the file.
  484. n, err = t.f1.Write([]byte("taco"))
  485. AssertEq(nil, err)
  486. AssertEq(4, n)
  487. // mmap the file.
  488. data, err := syscall.Mmap(
  489. int(t.f1.Fd()), 0, 4,
  490. syscall.PROT_READ|syscall.PROT_WRITE,
  491. syscall.MAP_SHARED)
  492. AssertEq(nil, err)
  493. defer syscall.Munmap(data)
  494. AssertEq("taco", string(data))
  495. // Close the file. We should see a flush.
  496. err = t.f1.Close()
  497. t.f1 = nil
  498. AssertEq(nil, err)
  499. AssertThat(t.getFlushes(), ElementsAre("taco"))
  500. AssertThat(t.getFsyncs(), ElementsAre())
  501. // Modify the contents.
  502. data[0] = 'p'
  503. // Unmap.
  504. err = syscall.Munmap(data)
  505. AssertEq(nil, err)
  506. // munmap does not cause a flush.
  507. ExpectThat(t.getFlushes(), ElementsAre("taco"))
  508. ExpectThat(t.getFsyncs(), ElementsAre())
  509. }
  510. func (t *NoErrorsTest) Mmap_WithMsync_MunmapBeforeClose() {
  511. var n int
  512. var err error
  513. var expectedFsyncs []interface{}
  514. // Open the file.
  515. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  516. AssertEq(nil, err)
  517. // Write some contents to the file.
  518. n, err = t.f1.Write([]byte("taco"))
  519. AssertEq(nil, err)
  520. AssertEq(4, n)
  521. // mmap the file.
  522. data, err := syscall.Mmap(
  523. int(t.f1.Fd()), 0, 4,
  524. syscall.PROT_READ|syscall.PROT_WRITE,
  525. syscall.MAP_SHARED)
  526. AssertEq(nil, err)
  527. defer syscall.Munmap(data)
  528. AssertEq("taco", string(data))
  529. // Modify the contents.
  530. data[0] = 'p'
  531. // msync. This causes an fsync, except on OS X (cf.
  532. // https://github.com/osxfuse/osxfuse/issues/202).
  533. err = msync(data)
  534. ExpectEq(nil, err)
  535. if !isDarwin {
  536. expectedFsyncs = append(expectedFsyncs, "paco")
  537. }
  538. ExpectThat(t.getFlushes(), ElementsAre())
  539. ExpectThat(t.getFsyncs(), ElementsAre(expectedFsyncs...))
  540. // Unmap. This does not cause anything.
  541. err = syscall.Munmap(data)
  542. AssertEq(nil, err)
  543. ExpectThat(t.getFlushes(), ElementsAre())
  544. ExpectThat(t.getFsyncs(), ElementsAre(expectedFsyncs...))
  545. // Close the file. We should now see a flush with the modified contents, even
  546. // on OS X.
  547. err = t.f1.Close()
  548. t.f1 = nil
  549. AssertEq(nil, err)
  550. ExpectThat(t.getFlushes(), ElementsAre("paco"))
  551. ExpectThat(t.getFsyncs(), ElementsAre(expectedFsyncs...))
  552. }
  553. func (t *NoErrorsTest) Mmap_WithMsync_CloseBeforeMunmap() {
  554. var n int
  555. var err error
  556. var expectedFsyncs []interface{}
  557. // Open the file.
  558. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  559. AssertEq(nil, err)
  560. // Write some contents to the file.
  561. n, err = t.f1.Write([]byte("taco"))
  562. AssertEq(nil, err)
  563. AssertEq(4, n)
  564. // mmap the file.
  565. data, err := syscall.Mmap(
  566. int(t.f1.Fd()), 0, 4,
  567. syscall.PROT_READ|syscall.PROT_WRITE,
  568. syscall.MAP_SHARED)
  569. AssertEq(nil, err)
  570. defer syscall.Munmap(data)
  571. AssertEq("taco", string(data))
  572. // Close the file. We should see a flush.
  573. err = t.f1.Close()
  574. t.f1 = nil
  575. AssertEq(nil, err)
  576. AssertThat(t.getFlushes(), ElementsAre("taco"))
  577. AssertThat(t.getFsyncs(), ElementsAre())
  578. // Modify the contents.
  579. data[0] = 'p'
  580. // msync. This causes an fsync, except on OS X (cf.
  581. // https://github.com/osxfuse/osxfuse/issues/202).
  582. err = msync(data)
  583. ExpectEq(nil, err)
  584. if !isDarwin {
  585. expectedFsyncs = append(expectedFsyncs, "paco")
  586. }
  587. ExpectThat(t.getFlushes(), ElementsAre("taco"))
  588. ExpectThat(t.getFsyncs(), ElementsAre(expectedFsyncs...))
  589. // Unmap. Again, this does not cause a flush.
  590. err = syscall.Munmap(data)
  591. AssertEq(nil, err)
  592. ExpectThat(t.getFlushes(), ElementsAre("taco"))
  593. ExpectThat(t.getFsyncs(), ElementsAre(expectedFsyncs...))
  594. }
  595. func (t *NoErrorsTest) Directory() {
  596. var err error
  597. // Open the directory.
  598. t.f1, err = os.Open(path.Join(t.Dir, "bar"))
  599. AssertEq(nil, err)
  600. // Sanity check: stat it.
  601. fi, err := t.f1.Stat()
  602. AssertEq(nil, err)
  603. AssertEq(0777|os.ModeDir, fi.Mode())
  604. // Sync it.
  605. err = t.f1.Sync()
  606. AssertEq(nil, err)
  607. // Close it.
  608. err = t.f1.Close()
  609. t.f1 = nil
  610. AssertEq(nil, err)
  611. // No flushes or fsync requests should have been received.
  612. ExpectThat(t.getFlushes(), ElementsAre())
  613. ExpectThat(t.getFsyncs(), ElementsAre())
  614. }
  615. ////////////////////////////////////////////////////////////////////////
  616. // Flush error
  617. ////////////////////////////////////////////////////////////////////////
  618. type FlushErrorTest struct {
  619. flushFSTest
  620. }
  621. func init() { RegisterTestSuite(&FlushErrorTest{}) }
  622. func (t *FlushErrorTest) SetUp(ti *TestInfo) {
  623. const noErr = 0
  624. t.flushFSTest.setUp(ti, syscall.ENOENT, noErr, false)
  625. }
  626. func (t *FlushErrorTest) Close() {
  627. var err error
  628. // Open the file.
  629. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  630. AssertEq(nil, err)
  631. // Close the file.
  632. err = t.f1.Close()
  633. t.f1 = nil
  634. ExpectThat(err, Error(HasSubstr("no such file")))
  635. }
  636. func (t *FlushErrorTest) Dup() {
  637. var err error
  638. // Open the file.
  639. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  640. AssertEq(nil, err)
  641. fd1 := t.f1.Fd()
  642. // Use dup(2) to get another copy.
  643. fd2, err := syscall.Dup(int(fd1))
  644. AssertEq(nil, err)
  645. t.f2 = os.NewFile(uintptr(fd2), t.f1.Name())
  646. // Close by the first handle. On OS X, where the semantics of file handles
  647. // are different (cf. https://github.com/osxfuse/osxfuse/issues/199), this
  648. // does not result in an error.
  649. err = t.f1.Close()
  650. t.f1 = nil
  651. if isDarwin {
  652. AssertEq(nil, err)
  653. } else {
  654. ExpectThat(err, Error(HasSubstr("no such file")))
  655. }
  656. // Close by the second handle.
  657. err = t.f2.Close()
  658. t.f2 = nil
  659. ExpectThat(err, Error(HasSubstr("no such file")))
  660. }
  661. func (t *FlushErrorTest) Dup2() {
  662. var err error
  663. // Open the file.
  664. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
  665. AssertEq(nil, err)
  666. // Create some anonymous temporary file.
  667. t.f2, err = fsutil.AnonymousFile("")
  668. AssertEq(nil, err)
  669. // Duplicate the temporary file descriptor on top of the file from our file
  670. // system. We shouldn't see the flush error.
  671. err = dup2(int(t.f2.Fd()), int(t.f1.Fd()))
  672. ExpectEq(nil, err)
  673. }
  674. ////////////////////////////////////////////////////////////////////////
  675. // Fsync error
  676. ////////////////////////////////////////////////////////////////////////
  677. type FsyncErrorTest struct {
  678. flushFSTest
  679. }
  680. func init() { RegisterTestSuite(&FsyncErrorTest{}) }
  681. func (t *FsyncErrorTest) SetUp(ti *TestInfo) {
  682. const noErr = 0
  683. t.flushFSTest.setUp(ti, noErr, syscall.ENOENT, false)
  684. }
  685. func (t *FsyncErrorTest) Fsync() {
  686. var err error
  687. // Open the file.
  688. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  689. AssertEq(nil, err)
  690. // Fsync.
  691. err = t.f1.Sync()
  692. ExpectThat(err, Error(HasSubstr("no such file")))
  693. }
  694. func (t *FsyncErrorTest) Fdatasync() {
  695. var err error
  696. if !fsutil.FdatasyncSupported {
  697. return
  698. }
  699. // Open the file.
  700. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  701. AssertEq(nil, err)
  702. // Fdatasync.
  703. err = fsutil.Fdatasync(t.f1)
  704. ExpectThat(err, Error(HasSubstr("no such file")))
  705. }
  706. func (t *FsyncErrorTest) Msync() {
  707. var err error
  708. // On OS X, msync does not cause SyncFile.
  709. if isDarwin {
  710. return
  711. }
  712. // Open the file.
  713. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
  714. AssertEq(nil, err)
  715. // mmap the file.
  716. data, err := syscall.Mmap(
  717. int(t.f1.Fd()), 0, 4,
  718. syscall.PROT_READ|syscall.PROT_WRITE,
  719. syscall.MAP_SHARED)
  720. AssertEq(nil, err)
  721. defer syscall.Munmap(data)
  722. // msync the mapping.
  723. err = msync(data)
  724. ExpectThat(err, Error(HasSubstr("no such file")))
  725. // Unmap.
  726. err = syscall.Munmap(data)
  727. AssertEq(nil, err)
  728. }
  729. ////////////////////////////////////////////////////////////////////////
  730. // Read-only mount
  731. ////////////////////////////////////////////////////////////////////////
  732. type ReadOnlyTest struct {
  733. flushFSTest
  734. }
  735. func init() { RegisterTestSuite(&ReadOnlyTest{}) }
  736. func (t *ReadOnlyTest) SetUp(ti *TestInfo) {
  737. const noErr = 0
  738. t.flushFSTest.setUp(ti, noErr, noErr, true)
  739. }
  740. func (t *ReadOnlyTest) ReadRoot() {
  741. var fi os.FileInfo
  742. // Read.
  743. entries, err := fusetesting.ReadDirPicky(t.Dir)
  744. AssertEq(nil, err)
  745. AssertEq(2, len(entries))
  746. // bar
  747. fi = entries[0]
  748. ExpectEq("bar", fi.Name())
  749. ExpectEq(os.FileMode(0777)|os.ModeDir, fi.Mode())
  750. // foo
  751. fi = entries[1]
  752. ExpectEq("foo", fi.Name())
  753. ExpectEq(os.FileMode(0777), fi.Mode())
  754. }
  755. func (t *ReadOnlyTest) StatFiles() {
  756. var fi os.FileInfo
  757. var err error
  758. // bar
  759. fi, err = os.Stat(path.Join(t.Dir, "bar"))
  760. AssertEq(nil, err)
  761. ExpectEq("bar", fi.Name())
  762. ExpectEq(os.FileMode(0777)|os.ModeDir, fi.Mode())
  763. // foo
  764. fi, err = os.Stat(path.Join(t.Dir, "foo"))
  765. AssertEq(nil, err)
  766. ExpectEq("foo", fi.Name())
  767. ExpectEq(os.FileMode(0777), fi.Mode())
  768. }
  769. func (t *ReadOnlyTest) ReadFile() {
  770. _, err := ioutil.ReadFile(path.Join(t.Dir, "foo"))
  771. ExpectEq(nil, err)
  772. }
  773. func (t *ReadOnlyTest) ReadDir() {
  774. _, err := fusetesting.ReadDirPicky(path.Join(t.Dir, "bar"))
  775. ExpectEq(nil, err)
  776. }
  777. func (t *ReadOnlyTest) CreateFile() {
  778. err := ioutil.WriteFile(path.Join(t.Dir, "blah"), []byte{}, 0400)
  779. ExpectThat(err, Error(HasSubstr("read-only")))
  780. }
  781. func (t *ReadOnlyTest) Mkdir() {
  782. err := os.Mkdir(path.Join(t.Dir, "blah"), 0700)
  783. ExpectThat(err, Error(HasSubstr("read-only")))
  784. }
  785. func (t *ReadOnlyTest) OpenForWrite() {
  786. modes := []int{
  787. os.O_WRONLY,
  788. os.O_RDWR,
  789. }
  790. for _, mode := range modes {
  791. f, err := os.OpenFile(path.Join(t.Dir, "foo"), mode, 0700)
  792. f.Close()
  793. ExpectThat(err, Error(HasSubstr("read-only")), "mode: %v", mode)
  794. }
  795. }
  796. func (t *ReadOnlyTest) Chtimes() {
  797. err := os.Chtimes(path.Join(t.Dir, "foo"), time.Now(), time.Now())
  798. ExpectThat(err, Error(MatchesRegexp("read-only|not permitted")))
  799. }
  800. func (t *ReadOnlyTest) Chmod() {
  801. err := os.Chmod(path.Join(t.Dir, "foo"), 0700)
  802. ExpectThat(err, Error(HasSubstr("read-only")))
  803. }