@@ -38,8 +38,8 @@ type file struct {
38
38
writeOnly bool
39
39
// Content encryption helper
40
40
contentEnc * contentenc.ContentEnc
41
- // Inode number
42
- ino uint64
41
+ // Device and inode number uniquely identify the backing file
42
+ devIno DevInoStruct
43
43
// File header
44
44
header * contentenc.FileHeader
45
45
// go-fuse nodefs.loopbackFile
@@ -59,13 +59,14 @@ func NewFile(fd *os.File, writeOnly bool, contentEnc *contentenc.ContentEnc) (no
59
59
tlog .Warn .Printf ("NewFile: Fstat on fd %d failed: %v\n " , fd .Fd (), err )
60
60
return nil , fuse .ToStatus (err )
61
61
}
62
- wlock .register (st .Ino )
62
+ di := DevInoFromStat (& st )
63
+ wlock .register (di )
63
64
64
65
return & file {
65
66
fd : fd ,
66
67
writeOnly : writeOnly ,
67
68
contentEnc : contentEnc ,
68
- ino : st . Ino ,
69
+ devIno : di ,
69
70
loopbackFile : nodefs .NewLoopbackFile (fd ),
70
71
}, fuse .OK
71
72
}
@@ -109,7 +110,7 @@ func (f *file) createHeader() error {
109
110
// Prevent partially written (=corrupt) header by preallocating the space beforehand
110
111
err := syscallcompat .EnospcPrealloc (int (f .fd .Fd ()), 0 , contentenc .HeaderLen )
111
112
if err != nil {
112
- tlog .Warn .Printf ("ino%d: createHeader: prealloc failed: %s\n " , f .ino , err .Error ())
113
+ tlog .Warn .Printf ("ino%d: createHeader: prealloc failed: %s\n " , f .devIno . ino , err .Error ())
113
114
return err
114
115
}
115
116
@@ -169,7 +170,7 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) {
169
170
plaintext , err := f .contentEnc .DecryptBlocks (ciphertext , firstBlockNo , f .header .ID )
170
171
if err != nil {
171
172
curruptBlockNo := firstBlockNo + f .contentEnc .PlainOffToBlockNo (uint64 (len (plaintext )))
172
- tlog .Warn .Printf ("ino%d: doRead: corrupt block #%d: %v" , f .ino , curruptBlockNo , err )
173
+ tlog .Warn .Printf ("ino%d: doRead: corrupt block #%d: %v" , f .devIno . ino , curruptBlockNo , err )
173
174
return nil , fuse .EIO
174
175
}
175
176
@@ -192,23 +193,23 @@ func (f *file) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fus
192
193
f .fdLock .RLock ()
193
194
defer f .fdLock .RUnlock ()
194
195
195
- tlog .Debug .Printf ("ino%d: FUSE Read: offset=%d length=%d" , f .ino , len (buf ), off )
196
+ tlog .Debug .Printf ("ino%d: FUSE Read: offset=%d length=%d" , f .devIno . ino , len (buf ), off )
196
197
197
198
if f .writeOnly {
198
- tlog .Warn .Printf ("ino%d: Tried to read from write-only file" , f .ino )
199
+ tlog .Warn .Printf ("ino%d: Tried to read from write-only file" , f .devIno . ino )
199
200
return nil , fuse .EBADF
200
201
}
201
202
202
203
out , status := f .doRead (uint64 (off ), uint64 (len (buf )))
203
204
204
205
if status == fuse .EIO {
205
- tlog .Warn .Printf ("ino%d: Read: returning EIO, offset=%d, length=%d" , f .ino , len (buf ), off )
206
+ tlog .Warn .Printf ("ino%d: Read: returning EIO, offset=%d, length=%d" , f .devIno . ino , len (buf ), off )
206
207
}
207
208
if status != fuse .OK {
208
209
return nil , status
209
210
}
210
211
211
- tlog .Debug .Printf ("ino%d: Read: status %v, returning %d bytes" , f .ino , status , len (out ))
212
+ tlog .Debug .Printf ("ino%d: Read: status %v, returning %d bytes" , f .devIno . ino , status , len (out ))
212
213
return fuse .ReadResultData (out ), status
213
214
}
214
215
@@ -250,7 +251,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
250
251
var oldData []byte
251
252
oldData , status = f .doRead (o , f .contentEnc .PlainBS ())
252
253
if status != fuse .OK {
253
- tlog .Warn .Printf ("ino%d fh%d: RMW read failed: %s" , f .ino , f .intFd (), status .String ())
254
+ tlog .Warn .Printf ("ino%d fh%d: RMW read failed: %s" , f .devIno . ino , f .intFd (), status .String ())
254
255
return written , status
255
256
}
256
257
// Modify
@@ -262,12 +263,12 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
262
263
blockOffset := b .BlockCipherOff ()
263
264
blockData = f .contentEnc .EncryptBlock (blockData , b .BlockNo , f .header .ID )
264
265
tlog .Debug .Printf ("ino%d: Writing %d bytes to block #%d" ,
265
- f .ino , uint64 (len (blockData ))- f .contentEnc .BlockOverhead (), b .BlockNo )
266
+ f .devIno . ino , uint64 (len (blockData ))- f .contentEnc .BlockOverhead (), b .BlockNo )
266
267
267
268
// Prevent partially written (=corrupt) blocks by preallocating the space beforehand
268
269
err := syscallcompat .EnospcPrealloc (int (f .fd .Fd ()), int64 (blockOffset ), int64 (len (blockData )))
269
270
if err != nil {
270
- tlog .Warn .Printf ("ino%d fh%d: doWrite: prealloc failed: %s" , f .ino , f .intFd (), err .Error ())
271
+ tlog .Warn .Printf ("ino%d fh%d: doWrite: prealloc failed: %s" , f .devIno . ino , f .intFd (), err .Error ())
271
272
status = fuse .ToStatus (err )
272
273
break
273
274
}
@@ -289,7 +290,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
289
290
// directly (in time and space) follows the last write.
290
291
// This is an optimisation for streaming writes on NFS where a
291
292
// Stat() call is very expensive.
292
- // The caller must "wlock.lock(f.ino)" otherwise this check would be racy.
293
+ // The caller must "wlock.lock(f.devIno. ino)" otherwise this check would be racy.
293
294
func (f * file ) isConsecutiveWrite (off int64 ) bool {
294
295
opCount := atomic .LoadUint64 (& wlock .opCount )
295
296
return opCount == f .lastOpCount + 1 && off == f .lastWrittenOffset + 1
@@ -305,12 +306,12 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
305
306
// The file descriptor has been closed concurrently, which also means
306
307
// the wlock has been freed. Exit here so we don't crash trying to access
307
308
// it.
308
- tlog .Warn .Printf ("ino%d fh%d: Write on released file" , f .ino , f .intFd ())
309
+ tlog .Warn .Printf ("ino%d fh%d: Write on released file" , f .devIno . ino , f .intFd ())
309
310
return 0 , fuse .EBADF
310
311
}
311
- wlock .lock (f .ino )
312
- defer wlock .unlock (f .ino )
313
- tlog .Debug .Printf ("ino%d: FUSE Write: offset=%d length=%d" , f .ino , off , len (data ))
312
+ wlock .lock (f .devIno )
313
+ defer wlock .unlock (f .devIno )
314
+ tlog .Debug .Printf ("ino%d: FUSE Write: offset=%d length=%d" , f .devIno . ino , off , len (data ))
314
315
// If the write creates a file hole, we have to zero-pad the last block.
315
316
// But if the write directly follows an earlier write, it cannot create a
316
317
// hole, and we can save one Stat() call.
@@ -332,13 +333,13 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
332
333
func (f * file ) Release () {
333
334
f .fdLock .Lock ()
334
335
if f .released {
335
- log .Panicf ("ino%d fh%d: double release" , f .ino , f .intFd ())
336
+ log .Panicf ("ino%d fh%d: double release" , f .devIno . ino , f .intFd ())
336
337
}
337
338
f .fd .Close ()
338
339
f .released = true
339
340
f .fdLock .Unlock ()
340
341
341
- wlock .unregister (f .ino )
342
+ wlock .unregister (f .devIno )
342
343
}
343
344
344
345
// Flush - FUSE call
0 commit comments