1 Title: Testing if a file system can be used for home directories...
2 Tags: english, nuug, debian edu
5 <p>A few years ago, I was involved in a project planning to use
6 Windows file servers as home directory servers for Debian
7 Edu/Skolelinux machines. This was thought to be no problem, as the
8 access would be through the SMB network file system protocol, and we
9 knew other sites used SMB with unix and samba as the file server to
10 mount home directories without any problems. But, after months of
11 struggling, we had to conclude that our goal was impossible.</p>
13 <p>The reason is simply that while SMB can be used for home
14 directories when the file server is Samba running on Unix, this only
15 work because of Samba have some extensions and the fact that the
16 underlying file system is a unix file system. When using a Windows
17 file server, the underlying file system do not have POSIX semantics,
18 and several programs will fail if the users home directory where they
19 want to store their configuration lack POSIX semantics.</p>
21 <p>As part of this work, I wrote a small C program I want to share
22 with you all, to replicate a few of the problematic applications (like
23 OpenOffice.org and GCompris) and see if the file system was working as
24 it should. If you find yourself in spooky file system land, it might
25 help you find your way out again. This is the fs-test.c source:</p>
29 * Some tests to check the file system sematics. Used to verify that
30 * CIFS from a windows server do not work properly as a linux home
32 * License: GPL v2 or later
34 * needs libsqlite3-dev and build-essential installed
35 * compile with: gcc -Wall -lsqlite3 -DTEST_SQLITE fs-test.c -o fs-test
38 #define _FILE_OFFSET_BITS 64
39 #define _LARGEFILE_SOURCE 1
40 #define _LARGEFILE64_SOURCE 1
42 #define _GNU_SOURCE /* for asprintf() */
47 #include <string.h>
48 #include <stdlib.h>
49 #include <sys/file.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <unistd.h>
56 * Test sqlite open, as done by gcompris require the libsqlite3-dev
57 * package and linking with -lsqlite3. A more low level test is
59 * See also <URL: http://www.sqlite.org./faq.html#q5 >.
61 #include <sqlite3.h>
62 #define CREATE_TABLE_USERS \
63 "CREATE TABLE users (user_id INT UNIQUE, login TEXT, lastname TEXT, firstname TEXT, birthdate TEXT, class_id INT ); "
64 int test_sqlite_open(void) {
66 char *name = "testsqlite.db";
69 int rc = sqlite3_open(name, &db);
71 printf("error: sqlite open of %s failed: %s\n", name, sqlite3_errmsg(db));
77 rc = sqlite3_exec(db,CREATE_TABLE_USERS, NULL, 0, &zErrMsg);
78 if( rc != SQLITE_OK ){
79 printf("error: sqlite table create failed: %s\n", zErrMsg);
83 printf("info: sqlite worked\n");
87 #endif /* TEST_SQLITE */
90 * Demonstrate locking issue found in gcompris using sqlite3. This
91 * work with ext3, but not with cifs server on Windows 2003. This is
92 * done in the sqlite3 library.
94 * <URL:http://www.cygwin.com/ml/cygwin/2001-08/msg00854.html> and the
96 * <URL:http://www.opengroup.org/onlinepubs/009695399/functions/fcntl.html>.
98 int test_gcompris_locking(void) {
100 char *name = "testsqlite.db";
102 int fd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0644);
103 printf("info: testing fcntl locking\n");
105 fl.l_whence = SEEK_SET;
107 printf(" Read-locking 1 byte from 1073741824");
108 fl.l_start = 1073741824;
111 if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
113 printf(" Read-locking 510 byte from 1073741826");
114 fl.l_start = 1073741826;
117 if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
119 printf(" Unlocking 1 byte from 1073741824");
120 fl.l_start = 1073741824;
123 if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
125 printf(" Write-locking 1 byte from 1073741824");
126 fl.l_start = 1073741824;
129 if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
131 printf(" Write-locking 510 byte from 1073741826");
132 fl.l_start = 1073741826;
134 if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
136 printf(" Unlocking 2 byte from 1073741824");
137 fl.l_start = 1073741824;
140 if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
147 * Test if permissions of freshly created directories allow entries
148 * below them. This was a problem with OpenOffice.org and gcompris.
149 * Mounting with option 'sync' seem to solve this problem while
150 * slowing down file operations.
152 int test_subdirectory_creation(void) {
154 char *path = strdup("test");
157 printf("info: testing subdirectory creation\n");
158 for (level = 0; level < LEVELS; level++) {
159 char *newpath = NULL;
160 if (-1 == mkdir(path, 0777)) {
161 printf(" error: Unable to create directory '%s': %s\n",
162 path, strerror(errno));
165 asprintf(&newpath, "%s/%s", path, "test");
173 * Test if symlinks can be created. This was a problem detected with
176 int test_symlinks(void) {
177 printf("info: testing symlink creation\n");
179 if (-1 == symlink("file", "symlink"))
180 printf(" error: Unable to create symlink\n");
184 int main(int argc, char **argv) {
185 printf("Testing POSIX/Unix sematics on file system\n");
187 test_subdirectory_creation();
190 #endif /* TEST_SQLITE */
191 test_gcompris_locking();
196 <p>When everything is working, it should print something like
200 Testing POSIX/Unix sematics on file system
201 info: testing symlink creation
202 info: testing subdirectory creation
204 info: testing fcntl locking
205 Read-locking 1 byte from 1073741824
206 Read-locking 510 byte from 1073741826
207 Unlocking 1 byte from 1073741824
208 Write-locking 1 byte from 1073741824
209 Write-locking 510 byte from 1073741826
210 Unlocking 2 byte from 1073741824
213 <p>I do not remember the exact details of the problems we saw, but one
214 of them was with locking, where if I remember correctly, POSIX allow a
215 read-only lock to be upgraded to a read-write lock without unlocking
216 the read-only lock (while Windows do not). Another was a bug in the
217 CIFS/SMB client implementation in the Linux kernel where directory
218 meta information would be wrong for a fraction of a second, making
219 OpenOffice.org fail to create its deep directory tree because it was
220 not allowed to create files in its freshly created directory.</p>
222 <p>Anyway, here is a nice tool for your tool box, might you never need
225 <p>Update 2010-08-27: Michael Gebetsroither report that he found the
226 script so useful that he created a GIT repository and stored it in
227 <a href="http://github.com/gebi/fs-test">http://github.com/gebi/fs-test</a>.</p>