summaryrefslogtreecommitdiffstats
path: root/fs/umsdos/specs
blob: 0f7d68c0aef6107d724913b467f4c3ec11c9161b (plain)
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/* #Specification: umsdos / readdir
 * umsdos_readdir() should fill a struct dirent with
 * an inode number. The cheap way to get it is to
 * do a lookup in the MSDOS directory for each
 * entry processed by the readdir() function.
 * This is not very efficient, but very simple. The
 * other way around is to maintain a copy of the inode
 * number in the EMD file. This is a problem because
 * this has to be maintained in sync using tricks.
 * Remember that MSDOS (the OS) does not update the
 * modification time (mtime) of a directory. There is
 * no easy way to tell that a directory was modified
 * during a DOS session and synchronise the EMD file.
 */
		/* #Specification: readdir / . and ..
		 * The msdos filesystem manages the . and .. entry properly
		 * so the EMD file won't hold any info about it.
		 * 
		 * In readdir, we assume that for the root directory
		 * the read position will be 0 for ".", 1 for "..". For
		 * a non root directory, the read position will be 0 for "."
		 * and 32 for "..".
		 */
		/*
		 * This is a trick used by the msdos file system (fs/msdos/dir.c)
		 * to manage . and .. for the root directory of a file system.
		 * Since there is no such entry in the root, fs/msdos/dir.c
		 * use the following:
		 * 
		 * if f_pos == 0, return ".".
		 * if f_pos == 1, return "..".
		 * 
		 * So let msdos handle it
		 * 
		 * Since umsdos entries are much larger, we share the same f_pos.
		 * if f_pos is 0 or 1 or 32, we are clearly looking at . and
		 * ..
		 * 
		 * As soon as we get f_pos == 2 or f_pos == 64, then back to
		 * 0, but this time we are reading the EMD file.
		 * 
		 * Well, not so true. The problem, is that UMSDOS_REC_SIZE is
		 * also 64, so as soon as we read the first record in the
		 * EMD, we are back at offset 64. So we set the offset
		 * to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the
		 * .. entry from msdos.
		 * 
		 * Now (linux 1.3), umsdos_readdir can read more than one
		 * entry even if we limit (umsdos_dir_once) to only one:
		 * It skips over hidden file. So we switch to
		 * UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully
		 * the .. entry.
		 */
			/* #Specification: umsdos / lookup / inode info
			 * After successfully reading an inode from the MSDOS
			 * filesystem, we use the EMD file to complete it.
			 * We update the following field.
			 * 
			 * uid, gid, atime, ctime, mtime, mode.
			 * 
			 * We rely on MSDOS for mtime. If the file
			 * was modified during an MSDOS session, at least
			 * mtime will be meaningful. We do this only for regular
			 * file.
			 * 
			 * We don't rely on MS-DOS for mtime for directories
			 * because the MS-DOS date on a directory is its
			 * creation time (strange MSDOS behavior) which
			 * corresponds to none of the three Unix time stamps.
			 */
	/* #Specification: umsdos / conversion mode
	 * The msdos filesystem can do some inline conversion
	 * of the data of a file.  It can translate silently
	 * from the MS-DOS text file format to the Unix one
	 * (CRLF -> LF) while reading, and the reverse
	 * while writing. This is activated using the mount
	 * option conv=....
	 * 
	 * This is not useful for Linux files in a promoted
	 * directory.  It can even be harmful.  For this
	 * reason, the binary (no conversion) mode is
	 * always activated.
	 */
	/* #Specification: umsdos / conversion mode / todo
	 * A flag could be added to file and directories
	 * forcing an automatic conversion mode (as
	 * done with the msdos filesystem).
	 * 
	 * This flag could be setup on a directory basis
	 * (instead of file) and all files in it would
	 * logically inherit it.  If the conversion mode
	 * is active (conv=) then the i_binary flag would
	 * be left untouched in those directories.
	 * 
	 * It was proposed that the sticky bit be used to set
	 * this.  A problem with that is that new files would
	 * be written incorrectly.  The other problem is that
	 * the sticky bit has a meaning for directories. So
	 * another bit should be used (there is some space
	 * in the EMD file for it) and a special utility
	 * would be used to assign the flag to a directory).
	 * I don't think it is useful to assign this flag
	 * on a single file.
	 */
 * #Specification: weakness / rename
 * There is a case where UMSDOS rename has a different behavior
 * than a normal Unix file system.  Renaming an open file across
 * directory boundary does not work.  Renaming an open file within
 * a directory does work, however.
 * 
 * The problem may is in Linux VFS driver for msdos.
 * I believe this is not a bug but a design feature, because
 * an inode number represents some sort of directory address
 * in the MSDOS directory structure, so moving the file into
 * another directory does not preserve the inode number.
 */
/* #Specification: rename / new name exist
 * If the destination name already exists, it will
 * silently be removed.  EXT2 does it this way
 * and this is the spec of SunOS.  So does UMSDOS.
 * 
 * If the destination is an empty directory it will
 * also be removed.
 */
/* #Specification: rename / new name exist / possible flaw
 * The code to handle the deletion of the target (file
 * and directory) use to be in umsdos_rename_f, surrounded
 * by proper directory locking.  This was ensuring that only
 * one process could achieve a rename (modification) operation
 * in the source and destination directory.  This was also
 * ensuring the operation was "atomic".
 * 
 * This has been changed because this was creating a
 * stack overflow (the stack is only 4 kB) in the kernel.  To avoid
 * the code doing the deletion of the target (if exist) has
 * been moved to a upper layer. umsdos_rename_f is tried
 * once and if it fails with EEXIST, the target is removed
 * and umsdos_rename_f is done again.
 * 
 * This makes the code cleaner and may solve a
 * deadlock problem one tester was experiencing.
 * 
 * The point is to mention that possibly, the semantic of
 * "rename" may be wrong. Anyone dare to check that :-)
 * Be aware that IF it is wrong, to produce the problem you
 * will need two process trying to rename a file to the
 * same target at the same time. Again, I am not sure it
 * is a problem at all.
 */

/* #Specification: hard link / strategy
 * Hard links are difficult to implement on top of an MS-DOS FAT file
 * system. Unlike Unix file systems, there are no inodes. A directory
 * entry holds the functionality of the inode and the entry.
 * 
 * We will used the same strategy as a normal Unix file system
 * (with inodes) except we will do it symbolically (using paths).
 * 
 * Because anything can happen during a DOS session (defragment,
 * directory sorting, etc.), we can't rely on an MS-DOS pseudo
 * inode number to record the link. For this reason, the link
 * will be done using hidden symbolic links. The following
 * scenario illustrates how it works.
 * 
 * Given a file /foo/file
 * 
 * #
 * ln /foo/file /tmp/file2
 * 
 * become internally
 * 
 * mv /foo/file /foo/-LINK1
 * ln -s /foo/-LINK1 /foo/file
 * ln -s /foo/-LINK1 /tmp/file2
 * #
 * 
 * Using this strategy, we can operate on /foo/file or /foo/file2.
 * We can remove one and keep the other, like a normal Unix hard link.
 * We can rename /foo/file or /tmp/file2 independently.
 * 
 * The entry -LINK1 will be hidden. It will hold a link count.
 * When all link are erased, the hidden file is erased too.
 */

/* #Specification: weakness / hard link
 * The strategy for hard link introduces a side effect that
 * may or may not be acceptable. Here is the sequence
 * 
 * #
 * mkdir subdir1
 * touch subdir1/file
 * mkdir subdir2
 * ln    subdir1/file subdir2/file
 * rm    subdir1/file
 * rmdir subdir1
 * rmdir: subdir1: Directory not empty
 * #
 * 
 * This happen because there is an invisible file (--link) in
 * subdir1 which is referenced by subdir2/file.
 * 
 * Any idea ?
 */
/* #Specification: weakness / hard link / rename directory
 * Another weakness of hard link come from the fact that
 * it is based on hidden symbolic links. Here is an example.
 * 
 * #
 * mkdir /subdir1
 * touch /subdir1/file
 * mkdir /subdir2
 * ln    /subdir1/file subdir2/file
 * mv    /subdir1 subdir3
 * ls -l /subdir2/file
 * #
 * 
 * Since /subdir2/file is a hidden symbolic link
 * to /subdir1/..hlinkNNN, accessing it will fail since
 * /subdir1 does not exist anymore (has been renamed).
 */
/* #Specification: hard link / directory
 * A hard link can't be made on a directory. EPERM is returned
 * in this case.
 */
/* #Specification: hard link / first hard link
 * The first time a hard link is done on a file, this
 * file must be renamed and hidden. Then an internal
 * symbolic link must be done on the hidden file.
 * 
 * The second link is done after on this hidden file.
 * 
 * It is expected that the Linux MSDOS file system
 * keeps the same pseudo inode when a rename operation
 * is done on a file in the same directory.
 */
/* #Specification: function name / convention
 * A simple convention for function names has been used in
 * the UMSDOS filesystem. First, all functions use the prefix
 * umsdos_ to avoid name clashes with other parts of the kernel.
 * 
 * Standard VFS entry points use the prefix UMSDOS (upper case)
 * so it's easier to tell them apart.
 * N.B. (FIXME) PTW, the order and contents of this struct changed.
 */

/* #Specification: mount / options
 * Umsdos run on top of msdos. Currently, it supports no
 * mount option, but happily pass all option received to
 * the msdos driver. I am not sure if all msdos mount option
 * make sense with Umsdos. Here are at least those who
 * are useful.
 * uid=
 * gid=
 * 
 * These options affect the operation of umsdos in directories
 * which do not have an EMD file. They behave like normal
 * msdos directory, with all limitation of msdos.
 */

/* #Specification: pseudo root / mount
 * When a umsdos fs is mounted, a special handling is done
 * if it is the root partition. We check for the presence
 * of the file /linux/etc/init or /linux/etc/rc or
 * /linux/sbin/init. If one is there, we do a chroot("/linux").
 * 
 * We check both because (see init/main.c) the kernel
 * try to exec init at different place and if it fails
 * it tries /bin/sh /etc/rc. To be consistent with
 * init/main.c, many more test would have to be done
 * to locate init. Any complain ?
 * 
 * The chroot is done manually in init/main.c but the
 * info (the inode) is located at mount time and store
 * in a global variable (pseudo_root) which is used at
 * different place in the umsdos driver. There is no
 * need to store this variable elsewhere because it
 * will always be one, not one per mount.
 * 
 * This feature allows the installation
 * of a linux system within a DOS system in a subdirectory.
 * 
 * A user may install its linux stuff in c:\linux
 * avoiding any clash with existing DOS file and subdirectory.
 * When linux boots, it hides this fact, showing a normal
 * root directory with /etc /bin /tmp ...
 * 
 * The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h
 * in the macro UMSDOS_PSDROOT_NAME.
 */