mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Send SETATTR request after open when atomic_o_trunc is not set.
In Linux, the VFS is responsible for implementing O_TRUNC. It does this by calling setattr with a zero size on the underlying inode. The sentry VFS does not have the same inode abstraction, so we need to implement the SETATTR behavior inside the fusefs implementation. PiperOrigin-RevId: 501385452
This commit is contained in:
committed by
gVisor bot
parent
69859a21f8
commit
320004cbe6
@@ -141,6 +141,7 @@ func (conn *connection) initProcessReply(out *linux.FUSEInitOut, hasSysAdminCap
|
||||
conn.bigWrites = out.Flags&linux.FUSE_BIG_WRITES != 0
|
||||
conn.dontMask = out.Flags&linux.FUSE_DONT_MASK != 0
|
||||
conn.writebackCache = out.Flags&linux.FUSE_WRITEBACK_CACHE != 0
|
||||
conn.atomicOTrunc = out.Flags&linux.FUSE_ATOMIC_O_TRUNC != 0
|
||||
|
||||
// TODO(gvisor.dev/issue/3195): figure out how to use TimeGran (0 < TimeGran <= fuseMaxTimeGranNs).
|
||||
|
||||
|
||||
@@ -476,15 +476,20 @@ func (i *inode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kernfs.Dentr
|
||||
fd.Nonseekable = true
|
||||
}
|
||||
|
||||
// If we don't send SETATTR before open (which is indicated by atomicOTrunc)
|
||||
// and O_TRUNC is set, update the inode's version number and clean existing data
|
||||
// by setting the file size to 0.
|
||||
if i.fs.conn.atomicOTrunc && opts.Flags&linux.O_TRUNC != 0 {
|
||||
i.fs.conn.mu.Lock()
|
||||
i.attributeVersion.Store(i.fs.conn.attributeVersion.Add(1))
|
||||
i.size.Store(0)
|
||||
i.fs.conn.mu.Unlock()
|
||||
i.attributeTime = 0
|
||||
// If atomicOTrunc and O_TRUNC are set, just update the inode's version number
|
||||
// and set its size to 0 since the truncation is handled by the FUSE daemon.
|
||||
// Otherwise send a separate SETATTR to truncate the file size.
|
||||
if opts.Flags&linux.O_TRUNC != 0 {
|
||||
if i.fs.conn.atomicOTrunc {
|
||||
i.fs.conn.mu.Lock()
|
||||
i.attributeVersion.Store(i.fs.conn.attributeVersion.Add(1))
|
||||
i.size.Store(0)
|
||||
i.fs.conn.mu.Unlock()
|
||||
i.attributeTime = 0
|
||||
} else {
|
||||
opts := vfs.SetStatOptions{Stat: linux.Statx{Size: 0, Mask: linux.STATX_SIZE}}
|
||||
i.setAttr(ctx, i.fs.VFSFilesystem(), auth.CredentialsFromContext(ctx), opts, true, i.newFhData.fh)
|
||||
}
|
||||
}
|
||||
|
||||
if err := fd.vfsfd.Init(fdImpl, opts.Flags, rp.Mount(), d.VFSDentry(), fdOptions); err != nil {
|
||||
|
||||
@@ -35,7 +35,8 @@ namespace testing {
|
||||
|
||||
constexpr char kMountOpts[] = "rootmode=755,user_id=0,group_id=0";
|
||||
|
||||
constexpr struct fuse_init_out kDefaultFUSEInitOutPayload = {.major = 7};
|
||||
constexpr struct fuse_init_out kDefaultFUSEInitOutPayload = {
|
||||
.major = 7, .minor = 14, .flags = FUSE_ATOMIC_O_TRUNC};
|
||||
|
||||
// Internal commands used to communicate between testing thread and the FUSE
|
||||
// server. See test/fuse/README.md for further detail.
|
||||
|
||||
@@ -128,6 +128,7 @@ syscall_test(
|
||||
syscall_test(
|
||||
add_overlay = True,
|
||||
test = "//test/syscalls/linux:creat_test",
|
||||
use_fusefs = True,
|
||||
)
|
||||
|
||||
syscall_test(
|
||||
|
||||
Reference in New Issue
Block a user