Screenshot instructions:
Windows
Mac
Red Hat Linux
Ubuntu
Click URL instructions:
Right-click on ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)
You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(11) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(1) |
Feb
(13) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
(3) |
Oct
(2) |
Nov
(21) |
Dec
(24) |
2004 |
Jan
(23) |
Feb
(45) |
Mar
(29) |
Apr
(16) |
May
(34) |
Jun
(93) |
Jul
(52) |
Aug
(38) |
Sep
(161) |
Oct
(124) |
Nov
(134) |
Dec
(80) |
2005 |
Jan
(182) |
Feb
(72) |
Mar
(149) |
Apr
(136) |
May
(154) |
Jun
(64) |
Jul
(122) |
Aug
(134) |
Sep
(171) |
Oct
(116) |
Nov
(184) |
Dec
(130) |
2006 |
Jan
(141) |
Feb
(146) |
Mar
(208) |
Apr
(96) |
May
(105) |
Jun
(103) |
Jul
(90) |
Aug
(85) |
Sep
(136) |
Oct
(142) |
Nov
(157) |
Dec
(90) |
2007 |
Jan
(56) |
Feb
(99) |
Mar
(154) |
Apr
(124) |
May
(153) |
Jun
(120) |
Jul
(205) |
Aug
(155) |
Sep
(104) |
Oct
(155) |
Nov
(162) |
Dec
(130) |
2008 |
Jan
(111) |
Feb
(99) |
Mar
(155) |
Apr
(159) |
May
(56) |
Jun
(147) |
Jul
(293) |
Aug
(260) |
Sep
(98) |
Oct
(103) |
Nov
(169) |
Dec
(117) |
2009 |
Jan
(97) |
Feb
(50) |
Mar
(132) |
Apr
(129) |
May
(117) |
Jun
(63) |
Jul
(59) |
Aug
(99) |
Sep
(96) |
Oct
(87) |
Nov
(188) |
Dec
(129) |
2010 |
Jan
(107) |
Feb
(160) |
Mar
(55) |
Apr
(99) |
May
(47) |
Jun
(142) |
Jul
(146) |
Aug
(84) |
Sep
(108) |
Oct
(122) |
Nov
(114) |
Dec
(44) |
2011 |
Jan
(67) |
Feb
(69) |
Mar
(96) |
Apr
(77) |
May
(182) |
Jun
(129) |
Jul
(115) |
Aug
(98) |
Sep
(80) |
Oct
(86) |
Nov
(99) |
Dec
(187) |
2012 |
Jan
(57) |
Feb
(65) |
Mar
(103) |
Apr
(106) |
May
(123) |
Jun
(107) |
Jul
(157) |
Aug
(81) |
Sep
(159) |
Oct
(117) |
Nov
(70) |
Dec
(78) |
2013 |
Jan
(167) |
Feb
(187) |
Mar
(71) |
Apr
(130) |
May
(85) |
Jun
(112) |
Jul
(95) |
Aug
(149) |
Sep
(43) |
Oct
(64) |
Nov
(45) |
Dec
(27) |
2014 |
Jan
(55) |
Feb
(68) |
Mar
(64) |
Apr
(61) |
May
(51) |
Jun
(80) |
Jul
(90) |
Aug
(63) |
Sep
(142) |
Oct
(113) |
Nov
(145) |
Dec
(24) |
2015 |
Jan
(20) |
Feb
(20) |
Mar
(61) |
Apr
(43) |
May
(44) |
Jun
(37) |
Jul
(43) |
Aug
(59) |
Sep
(85) |
Oct
(58) |
Nov
(47) |
Dec
(131) |
2016 |
Jan
(130) |
Feb
(47) |
Mar
(121) |
Apr
(131) |
May
(75) |
Jun
(55) |
Jul
(25) |
Aug
(56) |
Sep
(42) |
Oct
(92) |
Nov
(96) |
Dec
(74) |
2017 |
Jan
(124) |
Feb
(67) |
Mar
(41) |
Apr
(42) |
May
(48) |
Jun
(47) |
Jul
(51) |
Aug
(43) |
Sep
(63) |
Oct
(33) |
Nov
(35) |
Dec
(2) |
2018 |
Jan
(47) |
Feb
(24) |
Mar
(67) |
Apr
(23) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
1
(2) |
2
(1) |
3
|
4
(1) |
5
(3) |
6
(1) |
7
(1) |
8
(10) |
9
(6) |
10
(4) |
11
(2) |
12
(10) |
13
(14) |
14
(12) |
15
(2) |
16
(4) |
17
(1) |
18
(2) |
19
(15) |
20
(3) |
21
(2) |
22
(4) |
23
(13) |
24
(9) |
25
(5) |
26
(18) |
27
(7) |
28
(1) |
29
(5) |
30
(4) |
|
From: <jean-pierre.andre@wa...> - 2007-11-12 20:55:27
|
Hi Attached is a test program, which is derived from the standard fuse test program, I am having erratic problems with it. Above all, I would like to indicate I am not getting consistent results with it. Sometimes the result is as expected, so there might be some condition which I could disregard. The incorrect result neverless happens frequently on one machine (it is a double core one). When I trace the getattr() method issued by fuse for the stat(), I sometimes do not get the correct file name in the file system code : Instead of "/root/path/file2" I sometimes get "/root/path/somethingelse" Does that sound familiar to anybody, or is it just me being tired ? Thank you for any remarks about it. Note : I will be off tomorrow. Regards Jean-Pierre #include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> main(int argc, char *argv[]) { char testfile2[4096]; int f; const char *p; int res; int s; struct stat st; if ((argc != 2) || !getuid()) if (argc != 2) fprintf(stderr,"Need an argument (file name to be created)\$ else fprintf(stderr,"Should not be root\n"); else { /* create an available name for symb link */ strcpy(testfile2,argv[1]); strcat(testfile2,"2"); unlink(testfile2); /* create a plain file */ f = open(argv[1],O_WRONLY + O_CREAT + O_TRUNC, S_IREAD + S_IWRITE); if (f) { p = "some contents\n"; s = write(f,p,strlen(p)); if (s != strlen(p)) fprintf(stderr,"Failed to write\n"); close(f); /* make the symb link */ res = symlink(argv[1], testfile2); /* * the following may call fuse getattr() method * with a wrong path : the filename part of * the path is replaced by something else */ printf("stat(%s) : %d\n",testfile2,stat(testfile2,&st)); } else fprintf(stderr,"Could not create %s\n",argv[1]); } return (0); } |
From: Karol Grecki <kgrecki@gm...> - 2007-11-12 16:53:06
|
Hello, I've changed my desktop to Linux and I wanted to start using something else than samba to connect to my devbox. I have problems making nfs work on the other side so I tried sshfs. Unfortunately it's very slow. I did this on the same directory with ~10k files mounted with sshfs and samba: time ls -R >/dev/null samba 0.534s sshfs 14.784s I don't need lightening fast performance, I'm working with small files, but when I check code from svn I get 2 files a second... which makes it unusable. I've never used fuse/sshfs before, so I don't know what performance to expect, is there something wrong with my setup or is it just not suitable as a nfs/samba replacement? Cheers Karol -- View this message in context: http://www.nabble.com/sshfs-performance-tf4792327.html#a13709284 Sent from the Fuse - Dev mailing list archive at Nabble.com. |
From: Mark Washenberger <mwashenb@gm...> - 2007-11-12 15:11:53
|
It appears the direct_io options won't work out for me since I'll need to use mmap as well. Anybody else tried out my test code? On Nov 10, 2007 8:55 AM, Luis Furquim <luisfurquim@...> wrote: > Hello Mark > > I changed the log_test.c to it: > > . > . > . > unsigned char buf1[24], buf2[24], buf3[24]; > > . > . > . > if (close(fd1) =3D=3D -1) { > perror("close(fd1)"); > return -1; > } > > gets(buf3); > > if ((fd2 =3D open("log", O_RDWR)) =3D=3D -1) { > perror("open2"); > return -1; > } > > . > . > . > > Then I ran log_test and jut pressed enter when prompted to input. > The log is below, notice that there was no call to read, the same > behavior you are having. > > Nov 10 11:22:28 metatron ./grokfs: redirect_access(/, 1) > Nov 10 11:22:38 metatron ./grokfs: redirect_getattr(/log_test) > Nov 10 11:22:38 metatron ./grokfs: redirect_open(/log_test) > Nov 10 11:22:38 metatron ./grokfs: redirect_read(/log_test, off [0], > len [12288] > Nov 10 11:22:38 metatron ./grokfs: redirect_access(/log_test, 4) > Nov 10 11:22:38 metatron ./grokfs: redirect_flush(/log_test) > Nov 10 11:22:38 metatron ./grokfs: redirect_getattr(/temp1) > Nov 10 11:22:38 metatron ./grokfs: redirect_mknod(/temp1, 100600, 0) > Nov 10 11:22:38 metatron ./grokfs: redirect_getattr(/temp1) > Nov 10 11:22:38 metatron ./grokfs: redirect_open(/temp1) > Nov 10 11:22:38 metatron ./grokfs: redirect_getattr(/newlock) > Nov 10 11:22:38 metatron ./grokfs: redirect_link(/temp1, /newlock) > Nov 10 11:22:38 metatron ./grokfs: redirect_getattr(/newlock) > Nov 10 11:22:38 metatron ./grokfs: > redirect_getattr(/.fuse_hidden0000000300000001) > Nov 10 11:22:38 metatron ./grokfs: redirect_rename(/temp1, > /.fuse_hidden0000000300000001) > Nov 10 11:22:38 metatron ./grokfs: > redirect_write(/.fuse_hidden0000000300000001, off [0], len [24] > Nov 10 11:22:38 metatron ./grokfs: redirect_getattr(/log) > Nov 10 11:22:38 metatron ./grokfs: redirect_rename(/newlock, /log) > Nov 10 11:22:38 metatron ./grokfs: > redirect_flush(/.fuse_hidden0000000300000001) > Nov 10 11:22:38 metatron ./grokfs: > redirect_release(/.fuse_hidden0000000300000001) > Nov 10 11:22:38 metatron ./grokfs: > redirect_unlink(/.fuse_hidden0000000300000001) > Nov 10 11:22:39 metatron ./grokfs: redirect_open(/log) > Nov 10 11:22:39 metatron ./grokfs: redirect_flush(/log) > Nov 10 11:22:39 metatron ./grokfs: redirect_release(/log) > Nov 10 11:22:39 metatron ./grokfs: redirect_release(/log_test) > > Also, the log_test printed: Read 0 bytes from log > > Then I ran log_test again, this time, when prompted for input, > I changed to other command line terminal and typed ls -l fuse/ > forcing the system to do a getattr call on the "log" file. This time > your debug log showed the expected read call as you can see below: > > Nov 10 11:28:36 metatron ./grokfs: redirect_getattr(/log_test) > Nov 10 11:28:36 metatron ./grokfs: redirect_open(/log_test) > Nov 10 11:28:36 metatron ./grokfs: redirect_read(/log_test, off [0], > len [12288] > Nov 10 11:28:36 metatron ./grokfs: redirect_access(/log_test, 4) > Nov 10 11:28:36 metatron ./grokfs: redirect_flush(/log_test) > Nov 10 11:28:36 metatron ./grokfs: redirect_getattr(/temp1) > Nov 10 11:28:36 metatron ./grokfs: redirect_mknod(/temp1, 100600, 0) > Nov 10 11:28:36 metatron ./grokfs: redirect_getattr(/temp1) > Nov 10 11:28:36 metatron ./grokfs: redirect_open(/temp1) > Nov 10 11:28:36 metatron ./grokfs: redirect_getattr(/newlock) > Nov 10 11:28:36 metatron ./grokfs: redirect_link(/temp1, /newlock) > Nov 10 11:28:36 metatron ./grokfs: redirect_getattr(/newlock) > Nov 10 11:28:36 metatron ./grokfs: > redirect_getattr(/.fuse_hidden0000000600000002) > Nov 10 11:28:36 metatron ./grokfs: redirect_rename(/temp1, > /.fuse_hidden0000000600000002) > Nov 10 11:28:36 metatron ./grokfs: > redirect_write(/.fuse_hidden0000000600000002, off [0], len [24] > Nov 10 11:28:36 metatron ./grokfs: redirect_getattr(/log) > Nov 10 11:28:36 metatron ./grokfs: redirect_rename(/newlock, /log) > Nov 10 11:28:36 metatron ./grokfs: > redirect_flush(/.fuse_hidden0000000600000002) > Nov 10 11:28:36 metatron ./grokfs: > redirect_release(/.fuse_hidden0000000600000002) > Nov 10 11:28:36 metatron ./grokfs: > redirect_unlink(/.fuse_hidden0000000600000002) > Nov 10 11:28:39 metatron ./grokfs: redirect_opendir(/, <fuse_file_info>) > Nov 10 11:28:39 metatron ./grokfs: redirect_readdir(/, offset [0], ...) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/fuse) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/log_test.c) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/grokfs.c) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/Makefile) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/log) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/EXAMPLES) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/grokfs) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/grokfs.debug.log) > Nov 10 11:28:39 metatron ./grokfs: redirect_getattr(/log_test) > Nov 10 11:28:39 metatron ./grokfs: redirect_readdir(/, offset [2147483647= ], ...) > Nov 10 11:28:39 metatron ./grokfs: redirect_releasedir(/, <fuse_file_info= >) > Nov 10 11:28:41 metatron ./grokfs: redirect_getattr(/log) > Nov 10 11:28:41 metatron ./grokfs: redirect_open(/log) > Nov 10 11:28:41 metatron ./grokfs: redirect_read(/log, off [0], len [4096= ] > Nov 10 11:28:41 metatron ./grokfs: redirect_flush(/log) > Nov 10 11:28:41 metatron ./grokfs: redirect_release(/log) > Nov 10 11:28:41 metatron ./grokfs: redirect_release(/log_test) > > Also, the log_test printed: Read 24 bytes from log > > So, this confirm my suspicion. This is what is happening to grokfs: > > 1. when you rename("lock", "log"); the system must call your getattr > function to know if "log" exists or no. > > 2. The destiny file "log" does not exists, so you can rename to it > without caring anything. Then, FUSE caches the getattr results > for a while. You may chack this email talking something about > it http://article.gmane.org/gmane.comp.file-systems.fuse.devel/5342 > > 3. The subsequent call to open is made without a cal to your getattr > because it is cached, but the cache says it has 0 bytes... > > 4. When you try to read, fuse thinks it has no data and doesn't calls > your red. > > 5. In the second test, I got a successfull read because before opening > the "log" file, I forced an attribute refresh doing the "ls -l fuse/"= and > so, a new cache was done, this time telling fuse that the file has 24 > bytes of data. So, when log_test tried to read, fuse did the call to > your read function. > > I don't know how to fix this problem, maybe changing the attr_timeout, > maybe forcing the attribute refresh. Someone at fuse-devel can help > us? > > Best Regards > Luis Otavio Furquim > > 2007/11/9, Luis Furquim <luisfurquim@...>: > > > Hello > > > > I had no time now for taking a look at your code, I will do it later. > > But I made a > > brief look at it and noticed that you are not handling memory allocatio= n errors. > > If malloc, strdup et allii return you NULL, you write to it anyway and = frees it > > anyway. I think this is not the reason of your problem, because > > allocation errors > > will happen when your machine is heavy loaded stressed and I think > > that it's not > > the case on your tests. But it's a problem that can cause you nightmare= s in the > > future, because if you aren't handling it now because you are focusing= on the > > solution and are leaving it to handle in the future, I can tell you > > that I already > > done it before and I was gotten in a maze of allocations and no matter = how > > much I revised the code, I was always finding places where I forgot to = insert > > the error handling code. Also, error handling may lead you to big chang= es in > > the logic flow of a code, and then, you will be forced to do major chan= ges in > > big chunks of code. > > > > I truly think that the best way to avoid memory corruption bugs is to w= rite the > > code to handle them at the same time you write your code. It may appear= that > > we are wasting time, but we are actually reducing the total coding time= and > > raising a lot the stability of the code. > > > > Best Regards > > > > 2007/11/9, Mark Washenberger <mwashenb@...>: > > > Silly me, forgetting the attachment. > > > > > > On Nov 9, 2007 2:09 PM, Mark Washenberger <mwashenb@...> wrote: > > > > Fareha is correct. I separately tested this feature and found that > > > > when FUSE believes a file to be empty, it won't bother calling the > > > > read function given in fuse.c, which means no debugging output is > > > > given. > > > > > > > > The question then becomes, why does fuse think that the file I'm > > > > reading is empty? > > > > > > > > The access pattern that my application uses goes something like thi= s: > > > > > > > > fd =3D open("temp", O_CREAT|O_RDWR); > > > > link("temp", "lock"); > > > > unlink("temp"); > > > > pwrite(fd, buf, 24, 0); > > > > rename("lock", "log"); > > > > close(fd); > > > > > > > > fd2 =3D open("log", O_RDWR); > > > > pread(fd2, buf, 24, 0); > > > > close(fd2); > > > > > > > > The justification for this peculiar access pattern has to do with > > > > using rename to achieve file based locking with out flock() (not su= re > > > > but I'm stuck with it). In any case, this access pattern works just > > > > fine on my regular ext3 file system. However, using my > > > > passthrough+logging fuse file system, grokfs, the pread call result= s > > > > in an EOF. So it appears that fuse mistakenly believes the "log" fi= le > > > > to be empty, either voluntarily or through something I'm doing > > > > incorrectly in my grokfs implementation. > > > > > > > > I've attached my file system and the test code for the access patte= rn > > > > given above, along with examples of its use and the debug logging > > > > output. I'd love it if some of you gurus could take a look at it an= d > > > > help me figure out why this problem is occurring and any possible > > > > workarounds. > > > > > > > > Thanks, > > > > Mark > > > > > > > > > > > > > > > > On Nov 8, 2007 9:51 AM, Fareha Shafique <fareha@...> w= rote: > > > > > > > > > > I think if the file size is 0 (as returned by the getattr before = an > > > > > open), then fuse will not issue the read. It will just return 0. = If you > > > > > want it to still issue the read you have to define the direct_io = flag in > > > > > the open system call. > > > > > I'm not sure but this might be causing the behavior you're seeing= . > > > > > > > > > > -FS > > > > > > > > > > > > > > > > > > > > Mark Washenberger wrote: > > > > > > Yes, I have these defined for pread()/pwrite(), both in my file= system > > > > > > code and in my application. However, neither of those appear to= be the > > > > > > problem. > > > > > > > > > > > > When the application calls pread(), the request never makes it = into my > > > > > > file system code (i.e. my fuse_ops.read() function is never cal= led). > > > > > > So what I'd like to do is figure out why its returning 0 (EOF) = on this > > > > > > application call to pread. However, I do not know where to debu= g/trace > > > > > > this functionality. > > > > > > > > > > > > Thanks! > > > > > > > > > > > > On Nov 7, 2007 7:16 PM, Luis Furquim <luisfurquim@...> wr= ote: > > > > > > > > > > > >> Hi > > > > > >> > > > > > >> Is your filesystem open source? If so, have you included the f= ollowing > > > > > >> lines? > > > > > >> > > > > > >> #ifdef linux > > > > > >> /* For pread()/pwrite() */ > > > > > >> #define _XOPEN_SOURCE 500 > > > > > >> #endif > > > > > >> > > > > > >> Best Regards > > > > > >> Luis Otavio Furquim > > > > > >> > > > > > >> 2007/11/7, Mark Washenberger <mwashenb@...>: > > > > > >> > > > > > >>> > > > > > >>> Hello all, > > > > > >>> > > > > > >>> I have an application that calls pread on my fuse file system= (largely > > > > > >>> a pass-through at this point) and fails with a return value o= f 0. > > > > > >>> However, this call never registers with my particular .read f= unction > > > > > >>> in the fuse_operations struct I pass in to fuse_main, nor doe= s any > > > > > >>> "READ" function call appear in the debugging output (with the= -d > > > > > >>> option). I don't know much about fuse internals beyond lib/fu= se.c, so > > > > > >>> I can't seem to find a way to debug this. > > > > > >>> > > > > > >>> Is it possible that a pread call is being rejected without re= sorting > > > > > >>> to asking my particular file system implementation? That is, = something > > > > > >>> internal to fuse is rejecting this call, returning eof, witho= ut > > > > > >>> consulting me about the resource first? > > > > > >>> > > > > > >>> If it is possible, can you help me figure out at least where = I can > > > > > >>> debug this behavior? I'm looking to essentially see some kind= of debug > > > > > >>> output for every single read call request that is submitted t= o fuse, > > > > > >>> not just the ones that make it to fuse.c->fuse_read(. . .) > > > > > >>> > > > > > >>> I'm using Fuse 2.5.3. > > > > > >>> > > > > > >>> Thanks! > > > > > >>> > > > > > >>> Mark > > > > > >>> > > > > > >>> -------------------------------------------------------------= ------------ > > > > > >>> This SF.net email is sponsored by: Splunk Inc. > > > > > >>> Still grepping through log files to find problems? Stop. > > > > > >>> Now Search log events and configuration files using AJAX and = a browser. > > > > > >>> Download your FREE copy of Splunk now >> http://get.splunk.co= m/ > > > > > >>> _______________________________________________ > > > > > >>> fuse-devel mailing list > > > > > >>> fuse-devel@... > > > > > >>> https://lists.sourceforge.net/lists/listinfo/fuse-devel > > > > > >>> > > > > > >>> > > > > > >> > > > > > >> -- > > > > > >> Luis Ot=E1vio de Colla Furquim > > > > > >> N=E3o alimente os pingos > > > > > >> Don't feed the tribbles > > > > > >> http://www.furquim.org/chironfs/ > > > > > >> > > > > > > > > > > > > ---------------------------------------------------------------= ---------- > > > > > > This SF.net email is sponsored by: Splunk Inc. > > > > > > Still grepping through log files to find problems? Stop. > > > > > > Now Search log events and configuration files using AJAX and a = browser. > > > > > > Download your FREE copy of Splunk now >> http://get.splunk.com/ > > > > > > _______________________________________________ > > > > > > fuse-devel mailing list > > > > > > fuse-devel@... > > > > > > https://lists.sourceforge.net/lists/listinfo/fuse-devel > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > Luis Ot=E1vio de Colla Furquim > > N=E3o alimente os pingos > > Don't feed the tribbles > > http://www.furquim.org/chironfs/ > > > > > -- > > Luis Ot=E1vio de Colla Furquim > N=E3o alimente os pingos > Don't feed the tribbles > http://www.furquim.org/chironfs/ > |
From: Jean-Pierre ANDRE <jean-pierre.andre@wa...> - 2007-11-12 13:35:24
|
Quite fine. It is OK Thanks for your reply Regards Jean-Pierre > Message du 12/11/07 13:42 > De : "Miklos Szeredi" <miklos@...> > A : jean-pierre.andre@... > Copie =C3=A0 : fuse-devel@..., szaka@... > Objet : Re: [fuse-devel] ftruncate() behavior >=20 > > ftruncate() is supposed to check whether the > > file is being written, though it might be read-only. >=20 > The kernel checks that, so the filesystem need not do it. >=20 > So in ->ftruncate() the file handle is guaranteed to have been opened > for write. >=20 > Miklos >=20 > |
From: Miklos Szeredi <miklos@sz...> - 2007-11-12 13:22:42
|
> it seems that mtab_needs_update function will judge the /etc/mtab, and > just exits if the file is a symlink. I don't know what the function means. > Now I have to use umount directly if I want to umount it. Right. And that's buggy, since the filesystem still needs to be umounted, even if the mtab does not need modification. This patch against 2.7.1 should fix it. Thanks, Miklos Index: lib/mount_util.c =================================================================== RCS file: /cvsroot/fuse/fuse/lib/mount_util.c,v retrieving revision 1.8 diff -u -r1.8 mount_util.c --- lib/mount_util.c 16 Oct 2007 15:12:08 -0000 1.8 +++ lib/mount_util.c 12 Nov 2007 13:16:45 -0000 @@ -17,6 +17,7 @@ #include <mntent.h> #include <sys/stat.h> #include <sys/wait.h> +#include <sys/mount.h> static int mtab_needs_update(const char *mnt) { @@ -91,8 +92,13 @@ int res; int status; - if (!mtab_needs_update(mnt)) - return 0; + if (!mtab_needs_update(mnt)) { + res = umount2(mnt, lazy ? 2 : 0); + if (res == -1) + fprintf(stderr, "%s: failed to unmount %s: %s\n", progname, + mnt, strerror(errno)); + return res; + } res = fork(); if (res == -1) { |
From: Miklos Szeredi <miklos@sz...> - 2007-11-12 12:53:08
|
> how can i know which process is operating the file? fuse_get_context()->pid Miklos |
From: Miklos Szeredi <miklos@sz...> - 2007-11-12 12:51:03
|
> I am getting poor performance in the unlink operations with fuse. > > If I have a few different applications using the fuse mount and performing normal read and write operations, and in another application if I perform unlink at a top level directory of an unrelated single file, that will still cause fuse to come to a grinding halt. > > It looks like this is because fuse takes a global write lock. > > Is my assesment correct and is there any way to not run into this issue? Yes. Can you please try this patch against fuse-2.7.1? It should solve the issue. Thanks, Miklos Index: fuse/lib/fuse.c =================================================================== --- fuse.orig/lib/fuse.c 2007-10-08 19:42:55.000000000 +0200 +++ fuse/lib/fuse.c 2007-10-08 20:21:24.000000000 +0200 @@ -86,10 +86,10 @@ struct fuse { unsigned int generation; unsigned int hidectr; pthread_mutex_t lock; - pthread_rwlock_t tree_lock; struct fuse_config conf; int intr_installed; struct fuse_fs *fs; + pthread_cond_t treecond; }; struct lock { @@ -111,12 +111,13 @@ struct node { char *name; uint64_t nlookup; int open_count; - int is_hidden; struct timespec stat_updated; struct timespec mtime; off_t size; - int cache_valid; struct lock *locks; + unsigned int is_hidden : 1; + unsigned int cache_valid : 1; + int treelock; }; struct fuse_dh { @@ -351,6 +352,7 @@ static void delete_node(struct fuse *f, if (f->conf.debug) fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid); + assert(node->treelock == 0); assert(!node->name); unhash_id(f, node); free_node(node); @@ -402,9 +404,10 @@ static struct node *find_node(struct fus node->refctr = 1; node->nodeid = next_id(f); + node->generation = f->generation; node->open_count = 0; node->is_hidden = 0; - node->generation = f->generation; + node->treelock = 0; if (hash_name(f, node, parent, name) == -1) { free(node); node = NULL; @@ -433,45 +436,181 @@ static char *add_name(char *buf, char *s return s; } -static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name) +static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode, + struct node *end) +{ + struct node *node; + + if (wnode) { + assert(wnode->treelock == -1); + wnode->treelock = 0; + } + + for (node = get_node(f, nodeid); + node != end && node->nodeid != FUSE_ROOT_ID; + node = node->parent) { + assert(node->treelock > 0); + node->treelock--; + } +} + +static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name, + int lock, char **path, struct node **wnodep) { char buf[FUSE_MAX_PATH]; char *s = buf + FUSE_MAX_PATH - 1; struct node *node; + struct node *wnode = NULL; + int err; *s = '\0'; if (name != NULL) { s = add_name(buf, s, name); if (s == NULL) - return NULL; + return -ENAMETOOLONG; } - pthread_mutex_lock(&f->lock); - for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID; + if (wnodep) { + assert(lock); + wnode = lookup_node(f, nodeid, name); + if (wnode) { + if (wnode->treelock != 0) + return -EAGAIN; + + wnode->treelock = -1; + } + } + + err = 0; + for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID; node = node->parent) { - if (node->name == NULL) { - s = NULL; + err = -ENOENT; + if (node->name == NULL || node->parent == NULL) break; - } + err = -ENAMETOOLONG; s = add_name(buf, s, node->name); if (s == NULL) break; + + if (lock) { + err = -EAGAIN; + if (node->treelock == -1) + break; + node->treelock++; + } + err = 0; + } + + if (!err) { + s = strdup(s[0] ? s : "/"); + if (s != NULL) + *path = s; + else + err = -ENOMEM; + } + + if (err && lock) + unlock_path(f, nodeid, wnode, node); + + if (wnodep && !err) + *wnodep = wnode; + + return err; +} + +static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name, + char **path, struct node **wnode) +{ + int err; + + pthread_mutex_lock(&f->lock); + while (1) { + err = try_get_path(f, nodeid, name, 1, path, wnode); + if (err != -EAGAIN) + break; + + pthread_cond_wait(&f->treecond, &f->lock); } pthread_mutex_unlock(&f->lock); - if (node == NULL || s == NULL) - return NULL; - else if (*s == '\0') - return strdup("/"); - else - return strdup(s); + return err; +} + +static int get_path(struct fuse *f, fuse_ino_t nodeid, char **path) +{ + return get_path_common(f, nodeid, NULL, path, NULL); } -static char *get_path(struct fuse *f, fuse_ino_t nodeid) +static int get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name, + char **path) { - return get_path_name(f, nodeid, NULL); + return get_path_common(f, nodeid, name, path, NULL); +} + +static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name, + char **path, struct node **wnode) +{ + return get_path_common(f, nodeid, name, path, wnode); +} + +static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1, + fuse_ino_t nodeid2, const char *name2, + char **path1, char **path2, + struct node **wnode1, struct node **wnode2) +{ + int err; + + pthread_mutex_lock(&f->lock); + while (1) { + char *tmppath; + + /* FIXME: locking two paths needs deadlock checking */ + err = try_get_path(f, nodeid1, name1, 1, &tmppath, wnode1); + if (!err) { + err = try_get_path(f, nodeid2, name2, 1, path2, wnode2); + if (!err) + *path1 = tmppath; + else + unlock_path(f, nodeid1, wnode1 ? *wnode1 : NULL, NULL); + } + if (err != -EAGAIN) + break; + + pthread_cond_wait(&f->treecond, &f->lock); + } + pthread_mutex_unlock(&f->lock); + + return err; +} + +static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid, + struct node *wnode, char *path) +{ + pthread_mutex_lock(&f->lock); + unlock_path(f, nodeid, wnode, NULL); + pthread_cond_broadcast(&f->treecond); + pthread_mutex_unlock(&f->lock); + free(path); +} + +static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path) +{ + free_path_wrlock(f, nodeid, NULL, path); +} + +static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2, + struct node *wnode1, struct node *wnode2, + char *path1, char *path2) +{ + pthread_mutex_lock(&f->lock); + unlock_path(f, nodeid1, wnode1, NULL); + unlock_path(f, nodeid2, wnode2, NULL); + pthread_cond_broadcast(&f->treecond); + pthread_mutex_unlock(&f->lock); + free(path1); + free(path2); } static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup) @@ -481,6 +620,14 @@ static void forget_node(struct fuse *f, return; pthread_mutex_lock(&f->lock); node = get_node(f, nodeid); + + /* + * Node may still be locked due to interrupt idiocy in open, + * create and opendir + */ + while (node->nlookup == nlookup && node->treelock) + pthread_cond_wait(&f->treecond, &f->lock); + assert(node->nlookup >= nlookup); node->nlookup -= nlookup; if (!node->nlookup) { @@ -1128,9 +1275,11 @@ static char *hidden_name(struct fuse *f, (unsigned int) node->nodeid, f->hidectr); newnode = lookup_node(f, dir, newname); } while(newnode); + + newpath = NULL; + try_get_path(f, dir, newname, 0, &newpath, NULL); pthread_mutex_unlock(&f->lock); - newpath = get_path_name(f, dir, newname); if (!newpath) break; @@ -1240,7 +1389,7 @@ static struct fuse_context_i *fuse_get_c if (c == NULL) { /* This is hard to deal with properly, so just abort. If memory is so low that the context cannot be allocated, - there's not much hope for the filesystem anyway */ + there's not much hope for the filesystem anyway */ fprintf(stderr, "fuse: failed to allocate thread specific data\n"); abort(); } @@ -1358,14 +1507,12 @@ static void fuse_lib_lookup(fuse_req_t r char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path_name(f, parent, name); - if (path != NULL) { + err = get_path_name(f, parent, name, &path); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "LOOKUP %s\n", path); - fuse_prepare_interrupt(f, req, &d); + fuse_prepare_interrupt(f, req, &d); err = lookup_path(f, parent, name, path, &e, NULL); if (err == -ENOENT && f->conf.negative_timeout != 0.0) { e.ino = 0; @@ -1373,9 +1520,8 @@ static void fuse_lib_lookup(fuse_req_t r err = 0; } fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, parent, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err); } @@ -1400,17 +1546,14 @@ static void fuse_lib_getattr(fuse_req_t (void) fi; memset(&buf, 0, sizeof(buf)); - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_getattr(f->fs, path, &buf); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); if (!err) { if (f->conf.auto_cache) { pthread_mutex_lock(&f->lock); @@ -1440,19 +1583,17 @@ static void fuse_lib_setattr(fuse_req_t char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = 0; if (!err && (valid & FUSE_SET_ATTR_MODE)) err = fuse_fs_chmod(f->fs, path, attr->st_mode); if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) { - uid_t uid = + uid_t uid = (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1; - gid_t gid = + gid_t gid = (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1; err = fuse_fs_chown(f->fs, path, uid, gid); } @@ -1474,9 +1615,8 @@ static void fuse_lib_setattr(fuse_req_t if (!err) err = fuse_fs_getattr(f->fs, path, &buf); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); if (!err) { if (f->conf.auto_cache) { pthread_mutex_lock(&f->lock); @@ -1495,19 +1635,16 @@ static void fuse_lib_access(fuse_req_t r char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "ACCESS %s 0%o\n", path, mask); fuse_prepare_interrupt(f, req, &d); err = fuse_fs_access(f->fs, path, mask); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -1518,17 +1655,14 @@ static void fuse_lib_readlink(fuse_req_t char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname)); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); if (!err) { linkname[PATH_MAX] = '\0'; fuse_reply_readlink(req, linkname); @@ -1544,10 +1678,8 @@ static void fuse_lib_mknod(fuse_req_t re char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path_name(f, parent, name); - if (path) { + err = get_path_name(f, parent, name, &path); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "MKNOD %s\n", path); @@ -1570,9 +1702,8 @@ static void fuse_lib_mknod(fuse_req_t re err = lookup_path(f, parent, name, path, &e, NULL); } fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, parent, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err); } @@ -1584,10 +1715,8 @@ static void fuse_lib_mkdir(fuse_req_t re char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path_name(f, parent, name); - if (path != NULL) { + err = get_path_name(f, parent, name, &path); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "MKDIR %s\n", path); @@ -1596,9 +1725,8 @@ static void fuse_lib_mkdir(fuse_req_t re if (!err) err = lookup_path(f, parent, name, path, &e, NULL); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, parent, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err); } @@ -1606,41 +1734,38 @@ static void fuse_lib_unlink(fuse_req_t r const char *name) { struct fuse *f = req_fuse_prepare(req); + struct node *wnode; char *path; int err; - err = -ENOENT; - pthread_rwlock_wrlock(&f->tree_lock); - path = get_path_name(f, parent, name); - if (path != NULL) { + err = get_path_wrlock(f, parent, name, &path, &wnode); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "UNLINK %s\n", path); fuse_prepare_interrupt(f, req, &d); - if (!f->conf.hard_remove && is_open(f, parent, name)) + if (!f->conf.hard_remove && is_open(f, parent, name)) { err = hide_node(f, path, parent, name); - else { + } else { err = fuse_fs_unlink(f->fs, path); if (!err) remove_node(f, parent, name); } fuse_finish_interrupt(f, req, &d); - free(path); + free_path_wrlock(f, parent, wnode, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) { struct fuse *f = req_fuse_prepare(req); + struct node *wnode; char *path; int err; - err = -ENOENT; - pthread_rwlock_wrlock(&f->tree_lock); - path = get_path_name(f, parent, name); - if (path != NULL) { + err = get_path_wrlock(f, parent, name, &path, &wnode); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "RMDIR %s\n", path); @@ -1649,9 +1774,8 @@ static void fuse_lib_rmdir(fuse_req_t re fuse_finish_interrupt(f, req, &d); if (!err) remove_node(f, parent, name); - free(path); + free_path_wrlock(f, parent, wnode, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -1663,10 +1787,8 @@ static void fuse_lib_symlink(fuse_req_t char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path_name(f, parent, name); - if (path != NULL) { + err = get_path_name(f, parent, name, &path); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "SYMLINK %s\n", path); @@ -1675,9 +1797,8 @@ static void fuse_lib_symlink(fuse_req_t if (!err) err = lookup_path(f, parent, name, path, &e, NULL); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, parent, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err); } @@ -1688,32 +1809,28 @@ static void fuse_lib_rename(fuse_req_t r struct fuse *f = req_fuse_prepare(req); char *oldpath; char *newpath; + struct node *wnode1; + struct node *wnode2; int err; - err = -ENOENT; - pthread_rwlock_wrlock(&f->tree_lock); - oldpath = get_path_name(f, olddir, oldname); - if (oldpath != NULL) { - newpath = get_path_name(f, newdir, newname); - if (newpath != NULL) { - struct fuse_intr_data d; - if (f->conf.debug) - fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath); - err = 0; - fuse_prepare_interrupt(f, req, &d); - if (!f->conf.hard_remove && is_open(f, newdir, newname)) - err = hide_node(f, newpath, newdir, newname); - if (!err) { - err = fuse_fs_rename(f->fs, oldpath, newpath); - if (!err) - err = rename_node(f, olddir, oldname, newdir, newname, 0); - } - fuse_finish_interrupt(f, req, &d); - free(newpath); + err = get_path2(f, olddir, oldname, newdir, newname, + &oldpath, &newpath, &wnode1, &wnode2); + if (!err) { + struct fuse_intr_data d; + if (f->conf.debug) + fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath); + err = 0; + fuse_prepare_interrupt(f, req, &d); + if (!f->conf.hard_remove && is_open(f, newdir, newname)) + err = hide_node(f, newpath, newdir, newname); + if (!err) { + err = fuse_fs_rename(f->fs, oldpath, newpath); + if (!err) + err = rename_node(f, olddir, oldname, newdir, newname, 0); } - free(oldpath); + fuse_finish_interrupt(f, req, &d); + free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -1726,25 +1843,19 @@ static void fuse_lib_link(fuse_req_t req char *newpath; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - oldpath = get_path(f, ino); - if (oldpath != NULL) { - newpath = get_path_name(f, newparent, newname); - if (newpath != NULL) { - struct fuse_intr_data d; - if (f->conf.debug) - fprintf(stderr, "LINK %s\n", newpath); - fuse_prepare_interrupt(f, req, &d); - err = fuse_fs_link(f->fs, oldpath, newpath); - if (!err) - err = lookup_path(f, newparent, newname, newpath, &e, NULL); - fuse_finish_interrupt(f, req, &d); - free(newpath); - } - free(oldpath); + err = get_path2(f, ino, NULL, newparent, newname, + &oldpath, &newpath, NULL, NULL); + if (!err) { + struct fuse_intr_data d; + if (f->conf.debug) + fprintf(stderr, "LINK %s\n", newpath); + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_link(f->fs, oldpath, newpath); + if (!err) + err = lookup_path(f, newparent, newname, newpath, &e, NULL); + fuse_finish_interrupt(f, req, &d); + free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath); } - pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err); } @@ -1777,13 +1888,11 @@ static void fuse_lib_create(fuse_req_t r struct fuse *f = req_fuse_prepare(req); struct fuse_intr_data d; struct fuse_entry_param e; - char *path; + char *path = NULL; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path_name(f, parent, name); - if (path) { + err = get_path_name(f, parent, name, &path); + if (!err) { fuse_prepare_interrupt(f, req, &d); err = fuse_fs_create(f->fs, path, mode, fi); if (!err) { @@ -1821,16 +1930,14 @@ static void fuse_lib_create(fuse_req_t r } else reply_err(req, err); - if (path) - free(path); - - pthread_rwlock_unlock(&f->tree_lock); + if (path != NULL) + free_path(f, parent, path); } static double diff_timespec(const struct timespec *t1, const struct timespec *t2) { - return (t1->tv_sec - t2->tv_sec) + + return (t1->tv_sec - t2->tv_sec) + ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0; } @@ -1870,12 +1977,10 @@ static void fuse_lib_open(fuse_req_t req struct fuse *f = req_fuse_prepare(req); struct fuse_intr_data d; char *path = NULL; - int err = 0; + int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path) { + err = get_path(f, ino, &path); + if (!err) { fuse_prepare_interrupt(f, req, &d); err = fuse_fs_open(f->fs, path, fi); if (!err) { @@ -1905,9 +2010,8 @@ static void fuse_lib_open(fuse_req_t req } else reply_err(req, err); - if (path) - free(path); - pthread_rwlock_unlock(&f->tree_lock); + if (path != NULL) + free_path(f, ino, path); } static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size, @@ -1924,10 +2028,8 @@ static void fuse_lib_read(fuse_req_t req return; } - res = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + res = get_path(f, ino, &path); + if (res == 0) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "READ[%llu] %lu bytes from %llu\n", @@ -1937,9 +2039,8 @@ static void fuse_lib_read(fuse_req_t req fuse_prepare_interrupt(f, req, &d); res = fuse_fs_read(f->fs, path, buf, size, off, fi); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); if (res >= 0) { if (f->conf.debug) @@ -1961,10 +2062,8 @@ static void fuse_lib_write(fuse_req_t re char *path; int res; - res = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + res = get_path(f, ino, &path); + if (res == 0) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n", @@ -1974,9 +2073,8 @@ static void fuse_lib_write(fuse_req_t re fuse_prepare_interrupt(f, req, &d); res = fuse_fs_write(f->fs, path, buf, size, off, fi); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); if (res >= 0) { if (f->conf.debug) @@ -1997,19 +2095,16 @@ static void fuse_lib_fsync(fuse_req_t re char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; if (f->conf.debug) fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh); fuse_prepare_interrupt(f, req, &d); err = fuse_fs_fsync(f->fs, path, datasync, fi); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -2030,7 +2125,7 @@ static void fuse_lib_opendir(fuse_req_t struct fuse_intr_data d; struct fuse_dh *dh; struct fuse_file_info fi; - char *path; + char *path = NULL; int err; dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh)); @@ -2051,10 +2146,8 @@ static void fuse_lib_opendir(fuse_req_t memset(&fi, 0, sizeof(fi)); fi.flags = llfi->flags; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { fuse_prepare_interrupt(f, req, &d); err = fuse_fs_opendir(f->fs, path, &fi); fuse_finish_interrupt(f, req, &d); @@ -2073,8 +2166,8 @@ static void fuse_lib_opendir(fuse_req_t reply_err(req, err); free(dh); } - free(path); - pthread_rwlock_unlock(&f->tree_lock); + if (path != NULL) + free_path(f, ino, path); } static int extend_contents(struct fuse_dh *dh, unsigned minsize) @@ -2150,11 +2243,11 @@ static int readdir_fill(struct fuse *f, size_t size, off_t off, struct fuse_dh *dh, struct fuse_file_info *fi) { - int err = -ENOENT; char *path; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + int err; + + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; dh->len = 0; @@ -2170,9 +2263,8 @@ static int readdir_fill(struct fuse *f, err = dh->error; if (err) dh->filled = 0; - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); return err; } @@ -2218,16 +2310,15 @@ static void fuse_lib_releasedir(fuse_req struct fuse_intr_data d; struct fuse_file_info fi; struct fuse_dh *dh = get_dirhandle(llfi, &fi); - char *path; + char *path = NULL; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); + get_path(f, ino, &path); fuse_prepare_interrupt(f, req, &d); fuse_fs_releasedir(f->fs, path ? path : "-", &fi); fuse_finish_interrupt(f, req, &d); - if (path) - free(path); - pthread_rwlock_unlock(&f->tree_lock); + if (path != NULL) + free_path(f, ino, path); + pthread_mutex_lock(&dh->lock); pthread_mutex_unlock(&dh->lock); pthread_mutex_destroy(&dh->lock); @@ -2246,17 +2337,14 @@ static void fuse_lib_fsyncdir(fuse_req_t get_dirhandle(llfi, &fi); - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -2264,26 +2352,21 @@ static void fuse_lib_statfs(fuse_req_t r { struct fuse *f = req_fuse_prepare(req); struct statvfs buf; - char *path; - int err; + char *path = NULL; + int err = 0; memset(&buf, 0, sizeof(buf)); - pthread_rwlock_rdlock(&f->tree_lock); - if (!ino) { - err = -ENOMEM; - path = strdup("/"); - } else { - err = -ENOENT; - path = get_path(f, ino); - } - if (path) { + if (ino) + err = get_path(f, ino, &path); + + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); - err = fuse_fs_statfs(f->fs, path, &buf); + err = fuse_fs_statfs(f->fs, path ? path : "/", &buf); fuse_finish_interrupt(f, req, &d); - free(path); + if (path != NULL) + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); if (!err) fuse_reply_statfs(req, &buf); @@ -2298,17 +2381,14 @@ static void fuse_lib_setxattr(fuse_req_t char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_setxattr(f->fs, path, name, value, size, flags); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -2318,17 +2398,14 @@ static int common_getxattr(struct fuse * int err; char *path; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_getxattr(f->fs, path, name, value, size); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); return err; } @@ -2365,17 +2442,14 @@ static int common_listxattr(struct fuse char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_listxattr(f->fs, path, list, size); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); return err; } @@ -2412,17 +2486,14 @@ static void fuse_lib_removexattr(fuse_re char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_removexattr(f->fs, path, name); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -2578,11 +2649,10 @@ static void fuse_lib_release(fuse_req_t { struct fuse *f = req_fuse_prepare(req); struct fuse_intr_data d; - char *path; + char *path = NULL; int err = 0; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); + get_path(f, ino, &path); if (f->conf.debug) fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n", fi->flush ? "+FLUSH" : "", @@ -2597,8 +2667,8 @@ static void fuse_lib_release(fuse_req_t fuse_prepare_interrupt(f, req, &d); fuse_do_release(f, ino, path, fi); fuse_finish_interrupt(f, req, &d); - free(path); - pthread_rwlock_unlock(&f->tree_lock); + if (path != NULL) + free_path(f, ino, path); reply_err(req, err); } @@ -2607,16 +2677,16 @@ static void fuse_lib_flush(fuse_req_t re struct fuse_file_info *fi) { struct fuse *f = req_fuse_prepare(req); - char *path; + char *path = NULL; int err; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path && f->conf.debug) + get_path(f, ino, &path); + if (f->conf.debug) fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh); err = fuse_flush_common(f, req, ino, path, fi); - free(path); - pthread_rwlock_unlock(&f->tree_lock); + if (path != NULL) + free_path(f, ino, path); + reply_err(req, err); } @@ -2628,17 +2698,14 @@ static int fuse_lock_common(fuse_req_t r char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = fuse_fs_lock(f->fs, path, fi, cmd, lock); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); return err; } @@ -2693,16 +2760,13 @@ static void fuse_lib_bmap(fuse_req_t req char *path; int err; - err = -ENOENT; - pthread_rwlock_rdlock(&f->tree_lock); - path = get_path(f, ino); - if (path != NULL) { + err = get_path(f, ino, &path); + if (!err) { fuse_prepare_interrupt(f, req, &d); err = fuse_fs_bmap(f->fs, path, blocksize, &idx); fuse_finish_interrupt(f, req, &d); - free(path); + free_path(f, ino, path); } - pthread_rwlock_unlock(&f->tree_lock); if (!err) fuse_reply_bmap(req, idx); else @@ -2884,7 +2948,7 @@ static void fuse_lib_help(void) " -o readdir_ino try to fill in d_ino in readdir\n" " -o direct_io use direct I/O\n" " -o kernel_cache cache files in kernel\n" -" -o [no]auto_cache enable caching based on modification times\n" +" -o [no]auto_cache enable caching based on modification times (off)\n" " -o umask=M set file permissions (octal)\n" " -o uid=N set file owner\n" " -o gid=N set file group\n" @@ -3113,7 +3177,7 @@ struct fuse *fuse_new_common(struct fuse } fuse_mutex_init(&f->lock); - pthread_rwlock_init(&f->tree_lock, NULL); + pthread_cond_init(&f->treecond, NULL); root = (struct node *) calloc(1, sizeof(struct node)); if (root == NULL) { @@ -3189,8 +3253,8 @@ void fuse_destroy(struct fuse *f) for (node = f->id_table[i]; node != NULL; node = node->id_next) { if (node->is_hidden) { - char *path = get_path(f, node->nodeid); - if (path) { + char *path; + if (try_get_path(f, node->nodeid, NULL, 0, &path, NULL) == 0) { fuse_fs_unlink(f->fs, path); free(path); } @@ -3210,7 +3274,7 @@ void fuse_destroy(struct fuse *f) free(f->id_table); free(f->name_table); pthread_mutex_destroy(&f->lock); - pthread_rwlock_destroy(&f->tree_lock); + pthread_cond_destroy(&f->treecond); fuse_session_destroy(f->se); free(f->conf.modules); free(f); @@ -3252,7 +3316,7 @@ static struct fuse *fuse_new_common_comp struct fuse_args args = FUSE_ARGS_INIT(0, NULL); if (fuse_opt_add_arg(&args, "") == -1) - return NULL; + return NULL; if (opts && (fuse_opt_add_arg(&args, "-o") == -1 || fuse_opt_add_arg(&args, opts) == -1)) { |
From: Miklos Szeredi <miklos@sz...> - 2007-11-12 12:42:37
|
> ftruncate() is supposed to check whether the > file is being written, though it might be read-only. The kernel checks that, so the filesystem need not do it. So in ->ftruncate() the file handle is guaranteed to have been opened for write. Miklos |
From: robertsong <robertsong2000@gm...> - 2007-11-12 03:24:50
|
2007/11/10, Miklos Szeredi <miklos@...>: > > Now I am using fuse on my MIPS target board. > > And when I use fusermount -u to umount the filesystem, > > but It seems not to work. > > I found that the Changlog had said: > > Don't call /bin/[u]mount if /etc/mtab is a symlink. > > Now my /etc/mtab is a symlink of /proc/mounts. > > So I think I have only to use umount directly in this > > situation, is it right? > > Both 'fusermount -u' and 'umount' should work fine. > > Can you please do a > > strace -f -o /tmp/strace fusermount -u /mountpoint > > and send the resulting trace? > > Thanks, > Miklos > Miklos, thanks for you apply. I used the hello program to test fuse. $ hello /mnt/fuse $ fusermount -u /mnt/fuse the strace results are as below. 702 execve("/devel/usr/bin/fusermount", ["fusermount", "-u", "/mnt/fuse"], [/* 34 vars */]) = 0 702 brk(0) = 0x15000 702 uname({sys="Linux", node="10.1.137.2", ...}) = 0 702 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4001c000 702 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) 702 open("/devel/etc/ld.so.cache", O_RDONLY) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/v6l/fast-mult/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls/v6l/fast-mult/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/v6l/fast-mult/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls/v6l/fast-mult", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/v6l/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls/v6l/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/v6l/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls/v6l", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/fast-mult/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls/fast-mult/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/fast-mult/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls/fast-mult", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/tls", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/v6l/fast-mult/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/v6l/fast-mult/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/v6l/fast-mult/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/v6l/fast-mult", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/v6l/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/v6l/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/v6l/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/v6l", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/fast-mult/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/fast-mult/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/fast-mult/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/fast-mult", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/half/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 702 stat64("/devel/lib/half", 0xbea7dfc0) = -1 ENOENT (No such file or directory) 702 open("/devel/lib/libc.so.6", O_RDONLY) = 3 702 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0TM\1\0004\0\0\0"..., 512) = 512 702 fstat64(3, {st_mode=S_IFREG|0755, st_size=1410622, ...}) = 0 702 mmap2(NULL, 1147336, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x40025000 702 mprotect(0x40130000, 32768, PROT_NONE) = 0 702 mmap2(0x40138000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10b) = 0x40138000 702 mmap2(0x4013b000, 8648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4013b000 702 close(3) = 0 702 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4001d000 702 syscall_983045(0x4001d460, 0x4001d460, 0x6f4, 0x4001db30, 0x40024050, 0, 0x50, 0xf0005, 0xffff574c, 0x40024050, 0x40024000, 0xbea7e5b4, 0, 0xbea7e590, 0x8, 0x40001fa0, 0x20000010, 0x4001d460, 0, 0, 0, 0xdb40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 702 mprotect(0x40138000, 8192, PROT_READ) = 0 702 mprotect(0x40023000, 4096, PROT_READ) = 0 702 brk(0) = 0x15000 702 brk(0x36000) = 0x36000 702 getuid32() = 0 702 lstat64("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 702 getuid32() = 0 702 umask(033) = 022 702 geteuid32() = 0 702 getuid32() = 0 702 lstat64("/etc/mtab", {st_mode=S_IFLNK|0777, st_size=12, ...}) = 0 702 exit_group(0) = ? it seems that mtab_needs_update function will judge the /etc/mtab, and just exits if the file is a symlink. I don't know what the function means. Now I have to use umount directly if I want to umount it. thanks, robertsong |
From: tao li <mailinglist19@gm...> - 2007-11-12 02:29:51
|
hi,all how can i know which process is operating the file? thanks |