~james-w/+junk/fuse-debian-upstream

1
2
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
Here are some good questions and answers in no particular order.

---------------------------------------------------------------------------
Subject: FUSE vs. LUFS


> Can you explain me what are the differences between this two modules
> and why did you start a new project?

Well looking at the release dates on SF, the first release of FUSE is
almost a year older than that of LUFS.  But we probably weren't awere
of each others project for quite some time.

The main difference between them is that in LUFS the filesystem is a
shared object (.so) which is loaded by lufsmount, and in FUSE the
filesystem is a separate executable, which uses the fuse library.  The
actual API is very similar, and I've written a translator, that can
load LUFS modules and run them using the FUSE kernel module (see the
lufis package on the FUSE page).

Another difference is that LUFS does some caching of directories and
file attributes.  FUSE does not do this, so it provides a 'thinner'
interface.

---------------------------------------------------------------------------
Subject: close() not in struct fuse_operations


> Is there a reason for 'close' not being one of the
> fuse_operations? I'd need to know when files are
> closed...

It's not easy.  Consider mmap(): if you have a memory file, even after
closing it, you can read or write the file through memory.

Despite this there are close()-like operations: flush and release.
Flush gets called on each close() and release gets called when there
are no more uses of a file, including memory mappings.

---------------------------------------------------------------------------
Subject: overlapping open/release states


> I'm using a fairly current CVS version of Fuse, and have noticed
> overlapping open / release calls for a file.  In other words a file
> is opened multiple times and receives multiple release calls.  Is
> this expected?

It has always been like this.  The open / release calls correspond to
actual file opens / releases.  The release is called when there are no
more refernces to the file, i.e. on the last close() or munmap().

> This isn't what I expected.  Do I need to keep track of how many
> open() calls were made to a file and expect that many release() calls?

Yes.  You can also keep track of the number of files opened for
writing for example, and use that information for finally flushing
dirty data of a file.

> So it appears that there may even be additional file operations after
> one or more of the release calls..

That is expected also.  It would be a bug if there were reads/writes
after the last release, or if the number of releases didn't match the
number of opens.

> I've solved this in my code by counting the number of open / release
> calls and only dropping information when the last expected release
> is received.  But I thought I'd point this out in case, as it was
> unexpected behavior..

---------------------------------------------------------------------------
Subject: return value from release()


> Hmm.  So it doesn't matter what I return from my release function?  I
> understand there is not an exact 1:1 relationship between close() and
> release, but I had hoped that a error return from release would be
> carried up as an error return from close().

In release() the error value is ignored, and not every close will
cause a release.  Consider this:

  - process opens a file
  - process forks
  - parent closes the file
  - child closes the file

The file will only be released on the second close, i.e. when all
references to the file are closed.  Also memory mapping a file creates
a reference to the file, that is released when the memory is unmapped.

There is a flush() operation that is called on every close(), through
which the filesystem can return an error.

Note: there can be read/write operations even after the last flush()
but before a release().

---------------------------------------------------------------------------
Subject: FUSE lacks ioctl support


>  I'll try to add ioctl support to FUSE, but I am quite new to it, so I
>  would apreciate any suggestions.

It's not clear to me how would you use ioctls since they are
meaningless on normal files, and on device files the filesystem
implementation usually does not care about the ioctl operations.  And
even if you manage to hack fuse to intercept device ioctls, you
wouldn't be able to do anything with them, because they contain
arbitrarily structured data (not length/value as in the case of read
or write).

[...]

Using getxattr() and setxattr() is much cleaner than ioctl(), and is
actually supported in fuse-2.0.

---------------------------------------------------------------------------
Subject: Short reads


> Now for the problem case: I cat the 256k file, the kernel issues a
> read with length 65536 and offset 0.  My program returns only 10
> bytes.  What I expected to see was the kernel to then issue a read for
> length 65536 and offset 10.  Instead what I saw in the result was the
> 10 bytes I returned, followed by 65526 zero bytes.
>
> Is this the intended behavior?

Yes.  You can easily program around it with a for-loop in your read
function.

> Does this simplify things significantly?  If it isn't much of a
> difference, I'd like to suggest doing it the other way: many people
> (like me) implement their fuse read function in terms of read(), and
> read() can return early.

No.  Read from a pipe/socket can be short, but read from a file can't.

---------------------------------------------------------------------------
Subject: protocol error

> I'm having trouble with file writing. I can
> 'echo something > file' to a file, but
> 'cp file something' or 'cat something > file'
> gives a protocol error.

Two possible reasons for this are:

1) A mismatch between the library version and the kernel module
version.

2) The write() operation returns less than the 'size' parameter.
Short writes are generally not allowed (as in case of read()).  The
exception is if the 'direct_io' mount option is used.

---------------------------------------------------------------------------
Subject: FUSE naming


> There are a million other projects with the same name.  Why did you
> call it 'FUSE'?

Because I'm an imbecile.  The lesson is that a common term is not a
good project name.  A somewhat strange story comes to my mind: I was
contacted by Philip Kendall shortly after releasing FUSE, blaming me
for choosing the same name as his ZX Spectrum emulator (Fuse).  We
have known each other from earlier times, since I have also written a
ZX Spectrum emulator (Spectemu).

---------------------------------------------------------------------------
Subject: Uid/gid/pid


> Is there any easy way to know the uid of a reader?  For example, let's
> say I wanted to create a file that contained 'foo' for uid 1, but
> 'bar' for uid 2.

Yes:

fuse_get_context()->uid


---------------------------------------------------------------------------
Subject: 'find' command


> I'm having trouble getting the find command to search through fuse
> directories. What settings do I need in 'getattr'?

use the -noleaf option to find
(find uses the following parameters to determine whether it should recurse
into a subdirectory)

nr_links must be >= 3
size must be > 0
and must be a directory

so just return those in the getattr for your directories and you wont have
to use -noleaf.

---------------------------------------------------------------------------
Subject: File system interactivity

> I need to add interactivity to my user space file system.
> For example, while executing create(), I need to ask a
> question to the terminal that issued the request.
>
> Is there a way I can achieve this goal?

It would not be possible generally speaking, since it might not be an
interactive program but rather a daemon, or a GUI program creating the
file.  However you should be able to get the PID for the caller, and
by looking in /proc you should be able to find the process tty or
something similar. Perhaps it would be better to redesign your program
not to have such interactivity anyway, try to use e.g. extended
attributes of files to set per-file options, or a configuration file
for your filesystem.