03atomic_open.txt 2.93 KB
Newer Older
J. R. Okajima's avatar
J. R. Okajima committed
1

2
# Copyright (C) 2015-2020 Junjiro R. Okajima
J. R. Okajima's avatar
J. R. Okajima committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

Support for a branch who has its ->atomic_open()
----------------------------------------------------------------------
The filesystems who implement its ->atomic_open() are not majority. For
example NFSv4 does, and aufs should call NFSv4 ->atomic_open,
particularly for open(O_CREAT|O_EXCL, 0400) case. Other than
->atomic_open(), NFSv4 returns an error for this open(2). While I am not
sure whether all filesystems who have ->atomic_open() behave like this,
but NFSv4 surely returns the error.

In order to support ->atomic_open() for aufs, there are a few
approaches.

A. Introduce aufs_atomic_open()
   - calls one of VFS:do_last(), lookup_open() or atomic_open() for
     branch fs.
B. Introduce aufs_atomic_open() calling create, open and chmod. this is
   an aufs user Pip Cet's approach
   - calls aufs_create(), VFS finish_open() and notify_change().
   - pass fake-mode to finish_open(), and then correct the mode by
     notify_change().
C. Extend aufs_open() to call branch fs's ->atomic_open()
   - no aufs_atomic_open().
   - aufs_lookup() registers the TID to an aufs internal object.
   - aufs_create() does nothing when the matching TID is registered, but
     registers the mode.
   - aufs_open() calls branch fs's ->atomic_open() when the matching
     TID is registered.
D. Extend aufs_open() to re-try branch fs's ->open() with superuser's
   credential
   - no aufs_atomic_open().
   - aufs_create() registers the TID to an internal object. this info
     represents "this process created this file just now."
   - when aufs gets EACCES from branch fs's ->open(), then confirm the
     registered TID and re-try open() with superuser's credential.

Pros and cons for each approach.

A.
   - straightforward but highly depends upon VFS internal.
   - the atomic behavaiour is kept.
   - some of parameters such as nameidata are hard to reproduce for
     branch fs.
   - large overhead.
B.
   - easy to implement.
   - the atomic behavaiour is lost.
C.
   - the atomic behavaiour is kept.
   - dirty and tricky.
   - VFS checks whether the file is created correctly after calling
     ->create(), which means this approach doesn't work.
D.
   - easy to implement.
   - the atomic behavaiour is lost.
   - to open a file with superuser's credential and give it to a user
     process is a bad idea, since the file object keeps the credential
     in it. It may affect LSM or something. This approach doesn't work
     either.

The approach A is ideal, but it hard to implement. So here is a
variation of A, which is to be implemented.

A-1. Introduce aufs_atomic_open()
     - calls branch fs ->atomic_open() if exists. otherwise calls
       vfs_create() and finish_open().
     - the demerit is that the several checks after branch fs
       ->atomic_open() are lost. in the ordinary case, the checks are
       done by VFS:do_last(), lookup_open() and atomic_open(). some can
       be implemented in aufs, but not all I am afraid.