Discussion:
[Linux-HA] Problem with exportfs
Ulrich Windl
2013-02-01 07:24:46 UTC
Permalink
Hi!

While trying to develop an improved exportfs RA that can export one filesystem to a list of names (instead of just one name), I found an error:

exportfs is returning exit code 0 even if the filesystem could not be exported, like in
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success, even if the operation failed! That's due to

[...]
ocf_run exportfs -v ${OPTIONS} ${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]

However the monitor operation does the correct thing, thus reporting an error (rc==7).

This combination leads to the message of ocf-tester:
* rc=1: Monitoring an active resource should return 0

(The tester thinks the resource was started when it was not)

I had reported this for SLES10 SP2 to support in November, but after a long time of waiting and repeating the same facts over and over, support told me it's "working as designed"; lvscan and lvcreate would be similar.

A quick test showed that this is actually not true vor lvcreate:
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768 required.
5

I got the impression that my support is just unwilling to fix the rather trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.

Getting the exportfs sources, it took me two minutes to find out that exportfs uses variable export_errno to define the exit code, and that variable is nowhere set. The worker routine exportfs() does return nothing at all. What a design!

Here's an example from an old HP-UX system that didn't get any updates for three years:

# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1

Here it works!

I wonder why some Linux people are so ignorant occasionally...

Regards,
Ulrich
Dejan Muhamedagic
2013-02-01 07:53:39 UTC
Permalink
Hi,
Post by Ulrich Windl
Hi!
exportfs is returning exit code 0 even if the filesystem could not be exported, like in
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success, even if the operation failed! That's due to
[...]
ocf_run exportfs -v ${OPTIONS} ${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.

Thanks,

Dejan
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a long time of waiting and repeating the same facts over and over, support told me it's "working as designed"; lvscan and lvcreate would be similar.
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768 required.
5
I got the impression that my support is just unwilling to fix the rather trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Getting the exportfs sources, it took me two minutes to find out that exportfs uses variable export_errno to define the exit code, and that variable is nowhere set. The worker routine exportfs() does return nothing at all. What a design!
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
Googlemail
2013-02-01 08:06:26 UTC
Permalink
Post by Dejan Muhamedagic
Hi,
Post by Ulrich Windl
Hi!
exportfs is returning exit code 0 even if the filesystem could not be exported, like in
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success, even if the operation failed! That's due to
[...]
ocf_run exportfs -v ${OPTIONS} ${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a long time of waiting and repeating the same facts over and over, support told me it's "working as designed"; lvscan and lvcreate would be similar.
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768 required.
5
I got the impression that my support is just unwilling to fix the rather trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Getting the exportfs sources, it took me two minutes to find out that exportfs uses variable export_errno to define the exit code, and that variable is nowhere set. The worker routine exportfs() does return nothing at all. What a design!
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
RHEL6 shows the same behavior as SLES:
[root at rhel6 sbin]# exportfs h012:/mnt; echo $?
exportfs: Failed to resolve h012
0
Post by Dejan Muhamedagic
Post by Ulrich Windl
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
Ulrich Windl
2013-02-01 08:47:21 UTC
Permalink
Post by Ulrich Windl
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 08:53 in
Hi,
Post by Ulrich Windl
Hi!
While trying to develop an improved exportfs RA that can export one
exportfs is returning exit code 0 even if the filesystem could not be
exported, like in
Post by Ulrich Windl
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success,
even if the operation failed! That's due to
Post by Ulrich Windl
[...]
ocf_run exportfs -v ${OPTIONS}
${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
Post by Ulrich Windl
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an
error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Hi!

I'd fix the root of the problem: exportfs is unreliable!

Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a long
time of waiting and repeating the same facts over and over, support told me
it's "working as designed"; lvscan and lvcreate would be similar.
Post by Ulrich Windl
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768
required.
Post by Ulrich Windl
5
I got the impression that my support is just unwilling to fix the rather
trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Post by Ulrich Windl
Getting the exportfs sources, it took me two minutes to find out that
exportfs uses variable export_errno to define the exit code, and that
variable is nowhere set. The worker routine exportfs() does return nothing at
all. What a design!
Post by Ulrich Windl
Here's an example from an old HP-UX system that didn't get any updates for
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
Dejan Muhamedagic
2013-02-01 12:01:16 UTC
Permalink
Post by Ulrich Windl
Post by Ulrich Windl
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 08:53 in
Hi,
Post by Ulrich Windl
Hi!
While trying to develop an improved exportfs RA that can export one
exportfs is returning exit code 0 even if the filesystem could not be
exported, like in
Post by Ulrich Windl
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success,
even if the operation failed! That's due to
Post by Ulrich Windl
[...]
ocf_run exportfs -v ${OPTIONS}
${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
Post by Ulrich Windl
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an
error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Hi!
I'd fix the root of the problem: exportfs is unreliable!
That also, but it is probably going to take some time. Did you
open a bugzilla somewhere?

Thanks,

Dejan
Post by Ulrich Windl
Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a long
time of waiting and repeating the same facts over and over, support told me
it's "working as designed"; lvscan and lvcreate would be similar.
Post by Ulrich Windl
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768
required.
Post by Ulrich Windl
5
I got the impression that my support is just unwilling to fix the rather
trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Post by Ulrich Windl
Getting the exportfs sources, it took me two minutes to find out that
exportfs uses variable export_errno to define the exit code, and that
variable is nowhere set. The worker routine exportfs() does return nothing at
all. What a design!
Post by Ulrich Windl
Here's an example from an old HP-UX system that didn't get any updates for
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
Ulrich Windl
2013-02-04 07:35:21 UTC
Permalink
Post by Dejan Muhamedagic
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 13:01 in
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 08:53 in
Hi,
Post by Ulrich Windl
Hi!
While trying to develop an improved exportfs RA that can export one
filesystem to a list of names (instead of just one name), I found an
Post by Ulrich Windl
exportfs is returning exit code 0 even if the filesystem could not be
exported, like in
Post by Ulrich Windl
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success,
even if the operation failed! That's due to
Post by Ulrich Windl
[...]
ocf_run exportfs -v ${OPTIONS}
${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
Post by Ulrich Windl
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an
error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Hi!
I'd fix the root of the problem: exportfs is unreliable!
That also, but it is probably going to take some time. Did you
open a bugzilla somewhere?
Hi,

yes I did, but it didn't really help 8-(

Regards,
Ulrich
Post by Dejan Muhamedagic
Thanks,
Dejan
Post by Ulrich Windl
Regards,
Ulrich
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a
long
Post by Ulrich Windl
time of waiting and repeating the same facts over and over, support told
me
Post by Ulrich Windl
it's "working as designed"; lvscan and lvcreate would be similar.
Post by Ulrich Windl
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768
required.
Post by Ulrich Windl
5
I got the impression that my support is just unwilling to fix the rather
trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Post by Ulrich Windl
Getting the exportfs sources, it took me two minutes to find out that
exportfs uses variable export_errno to define the exit code, and that
variable is nowhere set. The worker routine exportfs() does return nothing
at
Post by Ulrich Windl
all. What a design!
Post by Ulrich Windl
Here's an example from an old HP-UX system that didn't get any updates for
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
Dejan Muhamedagic
2013-02-05 09:08:41 UTC
Permalink
Post by Ulrich Windl
Post by Dejan Muhamedagic
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 13:01 in
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 08:53 in
Hi,
Post by Ulrich Windl
Hi!
While trying to develop an improved exportfs RA that can export one
filesystem to a list of names (instead of just one name), I found an
Post by Ulrich Windl
exportfs is returning exit code 0 even if the filesystem could not be
exported, like in
Post by Ulrich Windl
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success,
even if the operation failed! That's due to
Post by Ulrich Windl
[...]
ocf_run exportfs -v ${OPTIONS}
${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
Post by Ulrich Windl
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an
error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Hi!
I'd fix the root of the problem: exportfs is unreliable!
That also, but it is probably going to take some time. Did you
open a bugzilla somewhere?
Hi,
yes I did, but it didn't really help 8-(
Do you want to share a link?

Thanks,

Dejan
Post by Ulrich Windl
Regards,
Ulrich
Post by Dejan Muhamedagic
Thanks,
Dejan
Post by Ulrich Windl
Regards,
Ulrich
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a
long
Post by Ulrich Windl
time of waiting and repeating the same facts over and over, support told
me
Post by Ulrich Windl
it's "working as designed"; lvscan and lvcreate would be similar.
Post by Ulrich Windl
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768
required.
Post by Ulrich Windl
5
I got the impression that my support is just unwilling to fix the rather
trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Post by Ulrich Windl
Getting the exportfs sources, it took me two minutes to find out that
exportfs uses variable export_errno to define the exit code, and that
variable is nowhere set. The worker routine exportfs() does return nothing
at
Post by Ulrich Windl
all. What a design!
Post by Ulrich Windl
Here's an example from an old HP-UX system that didn't get any updates for
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
Ulrich Windl
2013-02-13 13:03:16 UTC
Permalink
Hi!

I've made a patch to let exportfs propagate the errors it reported to the exit code of the process (see attachments, the compressed tar is there in case the mailer corrupts the patche files):

The exportfs seems to have been written with a "hot needle", not having error processing in mind. So I have to change the prototypes of several routines. Also one routine returns 1 on success, and 0 of failure, which is against all C conventions. Anyway, I've tested my code a littel bit, and it looks promising:

# non-root calling exportfs
./exportfs; echo $?
exportfs: could not open /var/lib/nfs/.etab.lock for locking: errno 13 (Permission denied)
1
# Empty export list
# ./exportfs; echo $?
0
# ./exportfs no-such-host:/tmp; echo $?
exportfs: Failed to resolve no-such-host
1
# existing host and filesystem
rksapv04:/tmp # ./exportfs localhost:/tmp; echo $?
0
# non-existing filesystem or directory
# ./exportfs localhost:/no-such-file; echo $?
exportfs: Failed to stat /no-such-file: No such file or directory
exportfs: localhost:/no-such-file: No such file or directory
1
# both incorrect
# ./exportfs no-host:/no-file; echo $?
exportfs: Failed to resolve no-host
exportfs: localhost:/no-such-file: No such file or directory
1
# unfortunately the non-existing filesystem is still exported:
# ./exportfs ; echo $?
/tmp localhost
/no-such-file localhost
0
# At least it can be unexported
# ./exportfs -u localhost:/no-such-file; echo $?
0

So the patch is not perfect, but probably a good staring point. Please send feedback!

Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 08:53 in
Hi,
Post by Ulrich Windl
Hi!
While trying to develop an improved exportfs RA that can export one
exportfs is returning exit code 0 even if the filesystem could not be
exported, like in
Post by Ulrich Windl
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success,
even if the operation failed! That's due to
Post by Ulrich Windl
[...]
ocf_run exportfs -v ${OPTIONS}
${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
Post by Ulrich Windl
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an
error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Hi!
I'd fix the root of the problem: exportfs is unreliable!
Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a long
time of waiting and repeating the same facts over and over, support told me
it's "working as designed"; lvscan and lvcreate would be similar.
Post by Ulrich Windl
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768
required.
Post by Ulrich Windl
5
I got the impression that my support is just unwilling to fix the rather
trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Post by Ulrich Windl
Getting the exportfs sources, it took me two minutes to find out that
exportfs uses variable export_errno to define the exit code, and that
variable is nowhere set. The worker routine exportfs() does return nothing
at
Post by Ulrich Windl
all. What a design!
Post by Ulrich Windl
Here's an example from an old HP-UX system that didn't get any updates for
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nfs-utils-1.2.7-exit-patch.tar.gz
Type: application/x-gzip
Size: 4508 bytes
Desc: not available
URL: <http://lists.linux-ha.org/pipermail/linux-ha/attachments/20130213/09343a2c/attachment.bin>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: 0001-Include-stdio.h-for-snprintf.patch
URL: <http://lists.linux-ha.org/pipermail/linux-ha/attachments/20130213/09343a2c/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: 0002-Let-exportfs-exit-with-error-on-errors.patch
URL: <http://lists.linux-ha.org/pipermail/linux-ha/attachments/20130213/09343a2c/attachment-0001.ksh>
Dejan Muhamedagic
2013-02-13 16:36:13 UTC
Permalink
Hi,
Post by Ulrich Windl
Hi!
You won't get the right audience here for exportfs (the
program). I'm not sure where the NFS stuff is discussed, but
there's probably a public forum somewhere.

Thanks,

Dejan
Post by Ulrich Windl
# non-root calling exportfs
./exportfs; echo $?
exportfs: could not open /var/lib/nfs/.etab.lock for locking: errno 13 (Permission denied)
1
# Empty export list
# ./exportfs; echo $?
0
# ./exportfs no-such-host:/tmp; echo $?
exportfs: Failed to resolve no-such-host
1
# existing host and filesystem
rksapv04:/tmp # ./exportfs localhost:/tmp; echo $?
0
# non-existing filesystem or directory
# ./exportfs localhost:/no-such-file; echo $?
exportfs: Failed to stat /no-such-file: No such file or directory
exportfs: localhost:/no-such-file: No such file or directory
1
# both incorrect
# ./exportfs no-host:/no-file; echo $?
exportfs: Failed to resolve no-host
exportfs: localhost:/no-such-file: No such file or directory
1
# ./exportfs ; echo $?
/tmp localhost
/no-such-file localhost
0
# At least it can be unexported
# ./exportfs -u localhost:/no-such-file; echo $?
0
So the patch is not perfect, but probably a good staring point. Please send feedback!
Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 08:53 in
Hi,
Post by Ulrich Windl
Hi!
While trying to develop an improved exportfs RA that can export one
exportfs is returning exit code 0 even if the filesystem could not be
exported, like in
Post by Ulrich Windl
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success,
even if the operation failed! That's due to
Post by Ulrich Windl
[...]
ocf_run exportfs -v ${OPTIONS}
${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
Post by Ulrich Windl
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an
error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Hi!
I'd fix the root of the problem: exportfs is unreliable!
Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a long
time of waiting and repeating the same facts over and over, support told me
it's "working as designed"; lvscan and lvcreate would be similar.
Post by Ulrich Windl
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768
required.
Post by Ulrich Windl
5
I got the impression that my support is just unwilling to fix the rather
trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Post by Ulrich Windl
Getting the exportfs sources, it took me two minutes to find out that
exportfs uses variable export_errno to define the exit code, and that
variable is nowhere set. The worker routine exportfs() does return nothing
at
Post by Ulrich Windl
all. What a design!
Post by Ulrich Windl
Here's an example from an old HP-UX system that didn't get any updates for
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
From 11c4a0d45a06169f2de8bd220509f4569a5c37c2 Mon Sep 17 00:00:00 2001
From: Ulrich Windl <Ulrich.Windl at RZ.Uni-Regensburg.DE>
Date: Wed, 13 Feb 2013 11:45:33 +0100
Subject: [PATCH 1/2] Include <stdio.h> for snprintf()
Include <stdio.h> to declare snprintf() in utils/nfsdcltrack/sqlite.c.
---
utils/nfsdcltrack/sqlite.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
index bac6789..f825873 100644
--- a/utils/nfsdcltrack/sqlite.c
+++ b/utils/nfsdcltrack/sqlite.c
@@ -38,6 +38,7 @@
#include "config.h"
#endif /* HAVE_CONFIG_H */
+#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <event.h>
--
1.7.12.4
From eaaa966427e64b247f67a22df3ed87fe6dd61923 Mon Sep 17 00:00:00 2001
From: Ulrich Windl <Ulrich.Windl at RZ.Uni-Regensburg.DE>
Date: Wed, 13 Feb 2013 13:24:54 +0100
Subject: [PATCH 2/2] Let exportfs exit with error on errors
xtab_read() and xtab_export_read() will return 0 on errors (strange logic,
but according to existing code).
cache_flush() will return 0 on success.
Changed export_all(), exportfs(), unexportfs(), exports_update(),
validate_export(), grab_lockfile(), release_lockfile() to return 0 on
success. Added verbose_release_lockfile() to keep atexit() happy.
Changed main() to return 1 on failure of any of: cache_flush(),
xtab_export_read(), grab_lockfile(), export_all(), exportfs(),
unexportfs(), exports_update(), xtab_export_write(), xtab_mount_write()
Changed exports_update_one() to return 0 on success, watching
export_export() and export_unexport() for errors.
Changed exports_update() to return 0 on success, watching
exports_update_one() for errors.
Changed export_all() to return 0 on success watching validate_export() for
errors.
Changed exportfs() to return 0 on success, watching updateexportent() and
validate_export() for errors.
Changed validate_export() to return 0 on success, watching test_export()
for errors.
---
support/export/xtab.c | 4 +-
support/include/nfslib.h | 2 +-
support/nfs/cacheio.c | 5 +-
utils/exportfs/exportfs.c | 173 ++++++++++++++++++++++++++++++----------------
4 files changed, 120 insertions(+), 64 deletions(-)
diff --git a/support/export/xtab.c b/support/export/xtab.c
index 2a43193..a87d453 100644
--- a/support/export/xtab.c
+++ b/support/export/xtab.c
@@ -24,6 +24,7 @@
int v4root_needed;
static void cond_rename(char *newfile, char *oldfile);
+/* return 0 on failure! */
static int
xtab_read(char *xtab, char *lockfn, int is_export)
{
@@ -63,7 +64,7 @@ xtab_read(char *xtab, char *lockfn, int is_export)
endexportent();
xfunlock(lockid);
- return 0;
+ return 1;
}
int
@@ -93,6 +94,7 @@ xtab_export_read(void)
* inode number changes when the xtab_export_write is done. If you change the
* routine below such that the files are edited in place, then you'll need to
* fix the auth_reload logic as well...
+ * Return 0 on failure!
*/
static int
xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export)
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
index f210a06..ee45f56 100644
--- a/support/include/nfslib.h
+++ b/support/include/nfslib.h
@@ -155,7 +155,7 @@ int qword_eol(FILE *f);
int readline(int fd, char **buf, int *lenp);
int qword_get(char **bpp, char *dest, int bufsize);
int qword_get_int(char **bpp, int *anint);
-void cache_flush(int force);
+int cache_flush(int force);
int check_new_cache(void);
void qword_add(char **bpp, int *lp, char *str);
void qword_addhex(char **bpp, int *lp, char *buf, int blen);
diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c
index e641c45..7ffca97 100644
--- a/support/nfs/cacheio.c
+++ b/support/nfs/cacheio.c
@@ -321,7 +321,7 @@ check_new_cache(void)
* auth.unix.ip nfsd.export nfsd.fh
*/
-void
+int
cache_flush(int force)
{
struct stat stb;
@@ -329,6 +329,7 @@ cache_flush(int force)
char stime[20];
char path[200];
time_t now;
+ int result = 0;
/* Note: the order of these caches is important.
* They need to be flushed in dependancy order. So
* a cache that references items in another cache,
@@ -357,8 +358,10 @@ cache_flush(int force)
if (write(fd, stime, strlen(stime)) != (ssize_t)strlen(stime)) {
xlog_warn("Writing to '%s' failed: errno %d (%s)",
path, errno, strerror(errno));
+ result = 1;
}
close(fd);
}
}
+ return result;
}
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index 9f79541..27ac8c3 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -34,18 +34,19 @@
#include "exportfs.h"
#include "xlog.h"
-static void export_all(int verbose);
-static void exportfs(char *arg, char *options, int verbose);
-static void unexportfs(char *arg, int verbose);
-static void exports_update(int verbose);
+static int export_all(int verbose);
+static int exportfs(char *arg, char *options, int verbose);
+static int unexportfs(char *arg, int verbose);
+static int exports_update(int verbose);
static void dump(int verbose);
static void error(nfs_export *exp, int err);
static void usage(const char *progname, int n);
-static void validate_export(nfs_export *exp);
+static int validate_export(nfs_export *exp);
static int matchhostname(const char *hostname1, const char *hostname2);
static void export_d_read(const char *dname);
-static void grab_lockfile(void);
-static void release_lockfile(void);
+static int grab_lockfile(void);
+static int release_lockfile(void);
+static void verbose_release_lockfile(void);
static const char *lockfile = EXP_LOCKFILE;
static int _lockfd = -1;
@@ -66,18 +67,28 @@ static int _lockfd = -1;
* corrupting etab, but to prevent problems like the above we
* need these additional lockfile() routines.
*/
-static void
+static int
grab_lockfile()
{
_lockfd = open(lockfile, O_CREAT|O_RDWR, 0666);
- if (_lockfd != -1)
- lockf(_lockfd, F_LOCK, 0);
+ if (_lockfd != -1 && lockf(_lockfd, F_LOCK, 0) == 0)
+ return 0;
+ return 1;
}
-static void
+
+static int
release_lockfile()
{
- if (_lockfd != -1)
- lockf(_lockfd, F_ULOCK, 0);
+ if (_lockfd != -1 && lockf(_lockfd, F_ULOCK, 0) == 0)
+ return 0;
+ return 1;
+}
+
+static void
+verbose_release_lockfile()
+{
+ if (release_lockfile())
+ xlog(L_ERROR, "problem releasing lockfile %s: %m", lockfile);
}
int
@@ -153,38 +164,44 @@ main(int argc, char **argv)
new_cache = check_new_cache();
if (optind == argc && ! f_all) {
if (force_flush) {
- if (new_cache)
- cache_flush(1);
- else {
+ if (new_cache) {
+ if (cache_flush(1))
+ export_errno = 1;
+ } else {
xlog(L_ERROR, "-f is available only "
"with new cache controls. "
"Mount /proc/fs/nfsd first");
return 1;
}
- return 0;
+ return export_errno;
} else {
- xtab_export_read();
+ if (xtab_export_read() == 0)
+ export_errno = 1;
dump(f_verbose);
- return 0;
+ return export_errno;
}
}
/*
* Serialize things as best we can
*/
- grab_lockfile();
- atexit(release_lockfile);
+ if (grab_lockfile())
+ export_errno = 1;
+ atexit(verbose_release_lockfile);
if (f_export && ! f_ignore) {
export_read(_PATH_EXPORTS);
export_d_read(_PATH_EXPORTS_D);
}
if (f_export) {
- if (f_all)
- export_all(f_verbose);
- else
- for (i = optind; i < argc ; i++)
- exportfs(argv[i], options, f_verbose);
+ if (f_all) {
+ if (export_all(f_verbose))
+ export_errno = 1;
+ } else
+ for (i = optind; i < argc ; i++) {
+ if (exportfs(argv[i], options, f_verbose))
+ export_errno = 1;
+ }
}
/* If we are unexporting everything, then
* don't care about what should be exported, as that
@@ -194,30 +211,41 @@ main(int argc, char **argv)
/* note: xtab_*_read does not update entries if they already exist,
* so this will not lose new options
*/
- if (!f_reexport)
- xtab_export_read();
+ if (!f_reexport) {
+ if (xtab_export_read() == 0)
+ export_errno = 1;
+ }
if (!f_export)
- for (i = optind ; i < argc ; i++)
- unexportfs(argv[i], f_verbose);
+ for (i = optind ; i < argc ; i++) {
+ if (unexportfs(argv[i], f_verbose))
+ export_errno = 1;
+ }
if (!new_cache)
rmtab_read();
}
if (!new_cache) {
xtab_mount_read();
- exports_update(f_verbose);
+ if (exports_update(f_verbose))
+ export_errno = 1;
+ }
+ if (!xtab_export_write())
+ export_errno = 1;
+ if (new_cache) {
+ if (cache_flush(force_flush))
+ export_errno = 1;
}
- xtab_export_write();
- if (new_cache)
- cache_flush(force_flush);
if (!new_cache)
- xtab_mount_write();
+ if (!xtab_mount_write())
+ export_errno = 1;
return export_errno;
}
-static void
+static int
exports_update_one(nfs_export *exp, int verbose)
{
+ int result = 0;
+
/* check mountpoint option */
if (exp->m_mayexport &&
exp->m_export.e_mountpoint &&
@@ -227,6 +255,7 @@ exports_update_one(nfs_export *exp, int verbose)
printf("%s not exported as %s not a mountpoint.\n",
exp->m_export.e_path, exp->m_export.e_mountpoint);
exp->m_mayexport = 0;
+ result = 1;
}
if (exp->m_mayexport && ((exp->m_exported<1) || exp->m_changed)) {
if (verbose)
@@ -234,17 +263,22 @@ exports_update_one(nfs_export *exp, int verbose)
exp->m_exported ?"re":"",
exp->m_client->m_hostname,
exp->m_export.e_path);
- if (!export_export(exp))
+ if (!export_export(exp)) {
error(exp, errno);
+ result = 1;
+ }
}
if (exp->m_exported && ! exp->m_mayexport) {
if (verbose)
printf("unexporting %s:%s from kernel\n",
exp->m_client->m_hostname,
exp->m_export.e_path);
- if (!export_unexport(exp))
+ if (!export_unexport(exp)) {
error(exp, errno);
+ result = 1;
+ }
}
+ return result;
}
@@ -253,28 +287,33 @@ exports_update_one(nfs_export *exp, int verbose)
* entries with m_exported but not m_mayexport get unexported
* looking at m_client->m_type == MCL_FQDN and m_client->m_type == MCL_GSS only
*/
-static void
+static int
exports_update(int verbose)
{
nfs_export *exp;
+ int result = 0;
for (exp = exportlist[MCL_FQDN].p_head; exp; exp=exp->m_next) {
- exports_update_one(exp, verbose);
+ if (exports_update_one(exp, verbose))
+ result = 1;
}
for (exp = exportlist[MCL_GSS].p_head; exp; exp=exp->m_next) {
- exports_update_one(exp, verbose);
+ if (exports_update_one(exp, verbose))
+ result = 1;
}
+ return result;
}
/*
- * export_all finds all entries and
- * marks them xtabent and mayexport so that they get exported
+ * export_all finds all entries and marks them xtabent and mayexport so that
+ * they get exported. Return 0 if thewre were no errors.
*/
-static void
+static int
export_all(int verbose)
{
nfs_export *exp;
int i;
+ int result = 0;
for (i = 0; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
@@ -286,13 +325,15 @@ export_all(int verbose)
exp->m_mayexport = 1;
exp->m_changed = 1;
exp->m_warned = 0;
- validate_export(exp);
+ if (validate_export(exp))
+ result = 1;
}
}
+ return result;
}
-
-static void
+/* return 0 on success */
+static int
exportfs(char *arg, char *options, int verbose)
{
struct exportent *eep;
@@ -301,13 +342,14 @@ exportfs(char *arg, char *options, int verbose)
char *path;
char *hname = arg;
int htype;
+ int result = 0;
if ((path = strchr(arg, ':')) != NULL)
*path++ = '\0';
if (!path || *path != '/') {
xlog(L_ERROR, "Invalid exporting option: %s", arg);
- return;
+ return 1;
}
if ((htype = client_gettype(hname)) == MCL_FQDN) {
@@ -321,10 +363,14 @@ exportfs(char *arg, char *options, int verbose)
if (!exp) {
if (!(eep = mkexportent(hname, path, options)) ||
- !(exp = export_create(eep, 0)))
+ !(exp = export_create(eep, 0))) {
+ result = 1;
goto out;
- } else if (!updateexportent(&exp->m_export, options))
+ }
+ } else if (!updateexportent(&exp->m_export, options)) {
+ result = 1;
goto out;
+ }
if (verbose)
printf("exporting %s:%s\n", exp->m_client->m_hostname,
@@ -333,13 +379,15 @@ exportfs(char *arg, char *options, int verbose)
exp->m_mayexport = 1;
exp->m_changed = 1;
exp->m_warned = 0;
- validate_export(exp);
+ result = validate_export(exp);
freeaddrinfo(ai);
+ return result;
}
-static void
+/* return 0 on success */
+static int
unexportfs(char *arg, int verbose)
{
nfs_export *exp;
@@ -347,13 +395,14 @@ unexportfs(char *arg, int verbose)
char *path;
char *hname = arg;
int htype;
+ int result = 0;
if ((path = strchr(arg, ':')) != NULL)
*path++ = '\0';
if (!path || *path != '/') {
xlog(L_ERROR, "Invalid unexporting option: %s", arg);
- return;
+ return 1;
}
if ((htype = client_gettype(hname)) == MCL_FQDN) {
@@ -396,6 +445,7 @@ unexportfs(char *arg, int verbose)
}
freeaddrinfo(ai);
+ return result;
}
static int can_test(void)
@@ -433,10 +483,11 @@ static int test_export(char *path, int with_fsid)
return 1;
}
-static void
+static int
validate_export(nfs_export *exp)
{
- /* Check that the given export point is potentially exportable.
+ /* Check that the given export point is potentially exportable,
+ * returning 0 on success.
* We just give warnings here, don't cause anything to fail.
* If a path doesn't exist, or is not a dir or file, give an warning
* otherwise trial-export to '-test-client-' and check for failure.
@@ -448,15 +499,15 @@ validate_export(nfs_export *exp)
if (stat(path, &stb) < 0) {
xlog(L_ERROR, "Failed to stat %s: %m", path);
- return;
+ return 1;
}
if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
xlog(L_ERROR, "%s is neither a directory nor a file. "
"Remote access will fail", path);
- return;
+ return 1;
}
if (!can_test())
- return;
+ return 1;
if (!statfs64(path, &stf) &&
(stf.f_fsid.__val[0] || stf.f_fsid.__val[1]))
@@ -466,16 +517,16 @@ validate_export(nfs_export *exp)
fs_has_fsid) {
if ( !test_export(path, 1)) {
xlog(L_ERROR, "%s does not support NFS export", path);
- return;
+ return 1;
}
} else if ( ! test_export(path, 0)) {
if (test_export(path, 1))
xlog(L_ERROR, "%s requires fsid= for NFS export", path);
else
xlog(L_ERROR, "%s does not support NFS export", path);
- return;
-
+ return 1;
}
+ return 0;
}
static _Bool
--
1.7.12.4
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
RaSca
2013-02-13 16:42:41 UTC
Permalink
Post by Dejan Muhamedagic
Hi,
Hi!
You won't get the right audience here for exportfs (the
program). I'm not sure where the NFS stuff is discussed, but
there's probably a public forum somewhere.
Thanks,
Dejan
[...]

There's an NFS ML, here: linux-nfs at vger.kernel.org it's the place were I
asked (three years ago) about exportfs
(http://en.usenet.digipedia.org/thread/18978/8062/).

Bye,
--
RaSca
Mia Mamma Usa Linux: Niente ? impossibile da capire, se lo spieghi bene!
rasca at miamammausalinux.org
http://www.miamammausalinux.org
J. Bruce Fields
2013-02-14 18:42:22 UTC
Permalink
Post by Ulrich Windl
Hi!
# non-root calling exportfs
./exportfs; echo $?
exportfs: could not open /var/lib/nfs/.etab.lock for locking: errno 13 (Permission denied)
1
# Empty export list
# ./exportfs; echo $?
0
# ./exportfs no-such-host:/tmp; echo $?
exportfs: Failed to resolve no-such-host
1
# existing host and filesystem
rksapv04:/tmp # ./exportfs localhost:/tmp; echo $?
0
# non-existing filesystem or directory
# ./exportfs localhost:/no-such-file; echo $?
exportfs: Failed to stat /no-such-file: No such file or directory
exportfs: localhost:/no-such-file: No such file or directory
1
# both incorrect
# ./exportfs no-host:/no-file; echo $?
exportfs: Failed to resolve no-host
exportfs: localhost:/no-such-file: No such file or directory
1
# ./exportfs ; echo $?
/tmp localhost
/no-such-file localhost
0
# At least it can be unexported
# ./exportfs -u localhost:/no-such-file; echo $?
0
So the patch is not perfect, but probably a good staring point. Please send feedback!
Thanks, agreed that this is worth fixing.

I'm used to the kernel convention:

int try_something(void)
{
return -ERRNO;
}

ret = try_something();
if (ret)
return ret;
...

so this convention is a bit alien to me, but I suppose it's fine as long
as we aren't losing any error information that the callers could use.

Cc'ing steved as this is an nfs-utils patch.

--b.
Post by Ulrich Windl
Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
Post by Ulrich Windl
Dejan Muhamedagic <dejanmm at fastmail.fm> schrieb am 01.02.2013 um 08:53 in
Hi,
Post by Ulrich Windl
Hi!
While trying to develop an improved exportfs RA that can export one
exportfs is returning exit code 0 even if the filesystem could not be
exported, like in
Post by Ulrich Windl
h02:~ # exportfs h012:/mnt; echo $? # h012 does not exist
exportfs: Failed to resolve h012
0
Accordingly the start operation for the exportfs alway reports success,
even if the operation failed! That's due to
Post by Ulrich Windl
[...]
ocf_run exportfs -v ${OPTIONS}
${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
Post by Ulrich Windl
# Restore the rmtab to ensure smooth NFS-over-TCP failover
restore_rmtab
ocf_log info "File system exported"
return $OCF_SUCCESS
[...]
However the monitor operation does the correct thing, thus reporting an
error (rc==7).
We could insert the monitor operation after the call to exportfs.
Would there be any timing issues? I guess not.
Thanks,
Dejan
Hi!
I'd fix the root of the problem: exportfs is unreliable!
Regards,
Ulrich
Post by Ulrich Windl
Post by Ulrich Windl
* rc=1: Monitoring an active resource should return 0
(The tester thinks the resource was started when it was not)
I had reported this for SLES10 SP2 to support in November, but after a long
time of waiting and repeating the same facts over and over, support told me
it's "working as designed"; lvscan and lvcreate would be similar.
Post by Ulrich Windl
# lvcreate -n bar -L40G foobar; echo $?
Volume group "foobar" not found
5
# lvcreate -n foo -L1T sys; echo $?
Volume group "sys" has insufficient free space (1855 extents): 32768
required.
Post by Ulrich Windl
5
I got the impression that my support is just unwilling to fix the rather
trivial problem. My exportfs comes from nfs-kernel-server-1.2.3-18.23.1.
Post by Ulrich Windl
Getting the exportfs sources, it took me two minutes to find out that
exportfs uses variable export_errno to define the exit code, and that
variable is nowhere set. The worker routine exportfs() does return nothing
at
Post by Ulrich Windl
all. What a design!
Post by Ulrich Windl
Here's an example from an old HP-UX system that didn't get any updates for
# exportfs nohost:/mnt; echo $?
exportfs: no entry for nohost:/mnt in /etc/dfs/dfstab
1
Here it works!
I wonder why some Linux people are so ignorant occasionally...
Regards,
Ulrich
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
_______________________________________________
Linux-HA mailing list
Linux-HA at lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems
From 11c4a0d45a06169f2de8bd220509f4569a5c37c2 Mon Sep 17 00:00:00 2001
From: Ulrich Windl <Ulrich.Windl at RZ.Uni-Regensburg.DE>
Date: Wed, 13 Feb 2013 11:45:33 +0100
Subject: [PATCH 1/2] Include <stdio.h> for snprintf()
Include <stdio.h> to declare snprintf() in utils/nfsdcltrack/sqlite.c.
---
utils/nfsdcltrack/sqlite.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
index bac6789..f825873 100644
--- a/utils/nfsdcltrack/sqlite.c
+++ b/utils/nfsdcltrack/sqlite.c
@@ -38,6 +38,7 @@
#include "config.h"
#endif /* HAVE_CONFIG_H */
+#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <event.h>
--
1.7.12.4
Post by Ulrich Windl
From eaaa966427e64b247f67a22df3ed87fe6dd61923 Mon Sep 17 00:00:00 2001
From: Ulrich Windl <Ulrich.Windl at RZ.Uni-Regensburg.DE>
Date: Wed, 13 Feb 2013 13:24:54 +0100
Subject: [PATCH 2/2] Let exportfs exit with error on errors
xtab_read() and xtab_export_read() will return 0 on errors (strange logic,
but according to existing code).
cache_flush() will return 0 on success.
Changed export_all(), exportfs(), unexportfs(), exports_update(),
validate_export(), grab_lockfile(), release_lockfile() to return 0 on
success. Added verbose_release_lockfile() to keep atexit() happy.
Changed main() to return 1 on failure of any of: cache_flush(),
xtab_export_read(), grab_lockfile(), export_all(), exportfs(),
unexportfs(), exports_update(), xtab_export_write(), xtab_mount_write()
Changed exports_update_one() to return 0 on success, watching
export_export() and export_unexport() for errors.
Changed exports_update() to return 0 on success, watching
exports_update_one() for errors.
Changed export_all() to return 0 on success watching validate_export() for
errors.
Changed exportfs() to return 0 on success, watching updateexportent() and
validate_export() for errors.
Changed validate_export() to return 0 on success, watching test_export()
for errors.
---
support/export/xtab.c | 4 +-
support/include/nfslib.h | 2 +-
support/nfs/cacheio.c | 5 +-
utils/exportfs/exportfs.c | 173 ++++++++++++++++++++++++++++++----------------
4 files changed, 120 insertions(+), 64 deletions(-)
diff --git a/support/export/xtab.c b/support/export/xtab.c
index 2a43193..a87d453 100644
--- a/support/export/xtab.c
+++ b/support/export/xtab.c
@@ -24,6 +24,7 @@
int v4root_needed;
static void cond_rename(char *newfile, char *oldfile);
+/* return 0 on failure! */
static int
xtab_read(char *xtab, char *lockfn, int is_export)
{
@@ -63,7 +64,7 @@ xtab_read(char *xtab, char *lockfn, int is_export)
endexportent();
xfunlock(lockid);
- return 0;
+ return 1;
}
int
@@ -93,6 +94,7 @@ xtab_export_read(void)
* inode number changes when the xtab_export_write is done. If you change the
* routine below such that the files are edited in place, then you'll need to
* fix the auth_reload logic as well...
+ * Return 0 on failure!
*/
static int
xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export)
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
index f210a06..ee45f56 100644
--- a/support/include/nfslib.h
+++ b/support/include/nfslib.h
@@ -155,7 +155,7 @@ int qword_eol(FILE *f);
int readline(int fd, char **buf, int *lenp);
int qword_get(char **bpp, char *dest, int bufsize);
int qword_get_int(char **bpp, int *anint);
-void cache_flush(int force);
+int cache_flush(int force);
int check_new_cache(void);
void qword_add(char **bpp, int *lp, char *str);
void qword_addhex(char **bpp, int *lp, char *buf, int blen);
diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c
index e641c45..7ffca97 100644
--- a/support/nfs/cacheio.c
+++ b/support/nfs/cacheio.c
@@ -321,7 +321,7 @@ check_new_cache(void)
* auth.unix.ip nfsd.export nfsd.fh
*/
-void
+int
cache_flush(int force)
{
struct stat stb;
@@ -329,6 +329,7 @@ cache_flush(int force)
char stime[20];
char path[200];
time_t now;
+ int result = 0;
/* Note: the order of these caches is important.
* They need to be flushed in dependancy order. So
* a cache that references items in another cache,
@@ -357,8 +358,10 @@ cache_flush(int force)
if (write(fd, stime, strlen(stime)) != (ssize_t)strlen(stime)) {
xlog_warn("Writing to '%s' failed: errno %d (%s)",
path, errno, strerror(errno));
+ result = 1;
}
close(fd);
}
}
+ return result;
}
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index 9f79541..27ac8c3 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -34,18 +34,19 @@
#include "exportfs.h"
#include "xlog.h"
-static void export_all(int verbose);
-static void exportfs(char *arg, char *options, int verbose);
-static void unexportfs(char *arg, int verbose);
-static void exports_update(int verbose);
+static int export_all(int verbose);
+static int exportfs(char *arg, char *options, int verbose);
+static int unexportfs(char *arg, int verbose);
+static int exports_update(int verbose);
static void dump(int verbose);
static void error(nfs_export *exp, int err);
static void usage(const char *progname, int n);
-static void validate_export(nfs_export *exp);
+static int validate_export(nfs_export *exp);
static int matchhostname(const char *hostname1, const char *hostname2);
static void export_d_read(const char *dname);
-static void grab_lockfile(void);
-static void release_lockfile(void);
+static int grab_lockfile(void);
+static int release_lockfile(void);
+static void verbose_release_lockfile(void);
static const char *lockfile = EXP_LOCKFILE;
static int _lockfd = -1;
@@ -66,18 +67,28 @@ static int _lockfd = -1;
* corrupting etab, but to prevent problems like the above we
* need these additional lockfile() routines.
*/
-static void
+static int
grab_lockfile()
{
_lockfd = open(lockfile, O_CREAT|O_RDWR, 0666);
- if (_lockfd != -1)
- lockf(_lockfd, F_LOCK, 0);
+ if (_lockfd != -1 && lockf(_lockfd, F_LOCK, 0) == 0)
+ return 0;
+ return 1;
}
-static void
+
+static int
release_lockfile()
{
- if (_lockfd != -1)
- lockf(_lockfd, F_ULOCK, 0);
+ if (_lockfd != -1 && lockf(_lockfd, F_ULOCK, 0) == 0)
+ return 0;
+ return 1;
+}
+
+static void
+verbose_release_lockfile()
+{
+ if (release_lockfile())
+ xlog(L_ERROR, "problem releasing lockfile %s: %m", lockfile);
}
int
@@ -153,38 +164,44 @@ main(int argc, char **argv)
new_cache = check_new_cache();
if (optind == argc && ! f_all) {
if (force_flush) {
- if (new_cache)
- cache_flush(1);
- else {
+ if (new_cache) {
+ if (cache_flush(1))
+ export_errno = 1;
+ } else {
xlog(L_ERROR, "-f is available only "
"with new cache controls. "
"Mount /proc/fs/nfsd first");
return 1;
}
- return 0;
+ return export_errno;
} else {
- xtab_export_read();
+ if (xtab_export_read() == 0)
+ export_errno = 1;
dump(f_verbose);
- return 0;
+ return export_errno;
}
}
/*
* Serialize things as best we can
*/
- grab_lockfile();
- atexit(release_lockfile);
+ if (grab_lockfile())
+ export_errno = 1;
+ atexit(verbose_release_lockfile);
if (f_export && ! f_ignore) {
export_read(_PATH_EXPORTS);
export_d_read(_PATH_EXPORTS_D);
}
if (f_export) {
- if (f_all)
- export_all(f_verbose);
- else
- for (i = optind; i < argc ; i++)
- exportfs(argv[i], options, f_verbose);
+ if (f_all) {
+ if (export_all(f_verbose))
+ export_errno = 1;
+ } else
+ for (i = optind; i < argc ; i++) {
+ if (exportfs(argv[i], options, f_verbose))
+ export_errno = 1;
+ }
}
/* If we are unexporting everything, then
* don't care about what should be exported, as that
@@ -194,30 +211,41 @@ main(int argc, char **argv)
/* note: xtab_*_read does not update entries if they already exist,
* so this will not lose new options
*/
- if (!f_reexport)
- xtab_export_read();
+ if (!f_reexport) {
+ if (xtab_export_read() == 0)
+ export_errno = 1;
+ }
if (!f_export)
- for (i = optind ; i < argc ; i++)
- unexportfs(argv[i], f_verbose);
+ for (i = optind ; i < argc ; i++) {
+ if (unexportfs(argv[i], f_verbose))
+ export_errno = 1;
+ }
if (!new_cache)
rmtab_read();
}
if (!new_cache) {
xtab_mount_read();
- exports_update(f_verbose);
+ if (exports_update(f_verbose))
+ export_errno = 1;
+ }
+ if (!xtab_export_write())
+ export_errno = 1;
+ if (new_cache) {
+ if (cache_flush(force_flush))
+ export_errno = 1;
}
- xtab_export_write();
- if (new_cache)
- cache_flush(force_flush);
if (!new_cache)
- xtab_mount_write();
+ if (!xtab_mount_write())
+ export_errno = 1;
return export_errno;
}
-static void
+static int
exports_update_one(nfs_export *exp, int verbose)
{
+ int result = 0;
+
/* check mountpoint option */
if (exp->m_mayexport &&
exp->m_export.e_mountpoint &&
@@ -227,6 +255,7 @@ exports_update_one(nfs_export *exp, int verbose)
printf("%s not exported as %s not a mountpoint.\n",
exp->m_export.e_path, exp->m_export.e_mountpoint);
exp->m_mayexport = 0;
+ result = 1;
}
if (exp->m_mayexport && ((exp->m_exported<1) || exp->m_changed)) {
if (verbose)
@@ -234,17 +263,22 @@ exports_update_one(nfs_export *exp, int verbose)
exp->m_exported ?"re":"",
exp->m_client->m_hostname,
exp->m_export.e_path);
- if (!export_export(exp))
+ if (!export_export(exp)) {
error(exp, errno);
+ result = 1;
+ }
}
if (exp->m_exported && ! exp->m_mayexport) {
if (verbose)
printf("unexporting %s:%s from kernel\n",
exp->m_client->m_hostname,
exp->m_export.e_path);
- if (!export_unexport(exp))
+ if (!export_unexport(exp)) {
error(exp, errno);
+ result = 1;
+ }
}
+ return result;
}
@@ -253,28 +287,33 @@ exports_update_one(nfs_export *exp, int verbose)
* entries with m_exported but not m_mayexport get unexported
* looking at m_client->m_type == MCL_FQDN and m_client->m_type == MCL_GSS only
*/
-static void
+static int
exports_update(int verbose)
{
nfs_export *exp;
+ int result = 0;
for (exp = exportlist[MCL_FQDN].p_head; exp; exp=exp->m_next) {
- exports_update_one(exp, verbose);
+ if (exports_update_one(exp, verbose))
+ result = 1;
}
for (exp = exportlist[MCL_GSS].p_head; exp; exp=exp->m_next) {
- exports_update_one(exp, verbose);
+ if (exports_update_one(exp, verbose))
+ result = 1;
}
+ return result;
}
/*
- * export_all finds all entries and
- * marks them xtabent and mayexport so that they get exported
+ * export_all finds all entries and marks them xtabent and mayexport so that
+ * they get exported. Return 0 if thewre were no errors.
*/
-static void
+static int
export_all(int verbose)
{
nfs_export *exp;
int i;
+ int result = 0;
for (i = 0; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
@@ -286,13 +325,15 @@ export_all(int verbose)
exp->m_mayexport = 1;
exp->m_changed = 1;
exp->m_warned = 0;
- validate_export(exp);
+ if (validate_export(exp))
+ result = 1;
}
}
+ return result;
}
-
-static void
+/* return 0 on success */
+static int
exportfs(char *arg, char *options, int verbose)
{
struct exportent *eep;
@@ -301,13 +342,14 @@ exportfs(char *arg, char *options, int verbose)
char *path;
char *hname = arg;
int htype;
+ int result = 0;
if ((path = strchr(arg, ':')) != NULL)
*path++ = '\0';
if (!path || *path != '/') {
xlog(L_ERROR, "Invalid exporting option: %s", arg);
- return;
+ return 1;
}
if ((htype = client_gettype(hname)) == MCL_FQDN) {
@@ -321,10 +363,14 @@ exportfs(char *arg, char *options, int verbose)
if (!exp) {
if (!(eep = mkexportent(hname, path, options)) ||
- !(exp = export_create(eep, 0)))
+ !(exp = export_create(eep, 0))) {
+ result = 1;
goto out;
- } else if (!updateexportent(&exp->m_export, options))
+ }
+ } else if (!updateexportent(&exp->m_export, options)) {
+ result = 1;
goto out;
+ }
if (verbose)
printf("exporting %s:%s\n", exp->m_client->m_hostname,
@@ -333,13 +379,15 @@ exportfs(char *arg, char *options, int verbose)
exp->m_mayexport = 1;
exp->m_changed = 1;
exp->m_warned = 0;
- validate_export(exp);
+ result = validate_export(exp);
freeaddrinfo(ai);
+ return result;
}
-static void
+/* return 0 on success */
+static int
unexportfs(char *arg, int verbose)
{
nfs_export *exp;
@@ -347,13 +395,14 @@ unexportfs(char *arg, int verbose)
char *path;
char *hname = arg;
int htype;
+ int result = 0;
if ((path = strchr(arg, ':')) != NULL)
*path++ = '\0';
if (!path || *path != '/') {
xlog(L_ERROR, "Invalid unexporting option: %s", arg);
- return;
+ return 1;
}
if ((htype = client_gettype(hname)) == MCL_FQDN) {
@@ -396,6 +445,7 @@ unexportfs(char *arg, int verbose)
}
freeaddrinfo(ai);
+ return result;
}
static int can_test(void)
@@ -433,10 +483,11 @@ static int test_export(char *path, int with_fsid)
return 1;
}
-static void
+static int
validate_export(nfs_export *exp)
{
- /* Check that the given export point is potentially exportable.
+ /* Check that the given export point is potentially exportable,
+ * returning 0 on success.
* We just give warnings here, don't cause anything to fail.
* If a path doesn't exist, or is not a dir or file, give an warning
* otherwise trial-export to '-test-client-' and check for failure.
@@ -448,15 +499,15 @@ validate_export(nfs_export *exp)
if (stat(path, &stb) < 0) {
xlog(L_ERROR, "Failed to stat %s: %m", path);
- return;
+ return 1;
}
if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
xlog(L_ERROR, "%s is neither a directory nor a file. "
"Remote access will fail", path);
- return;
+ return 1;
}
if (!can_test())
- return;
+ return 1;
if (!statfs64(path, &stf) &&
(stf.f_fsid.__val[0] || stf.f_fsid.__val[1]))
@@ -466,16 +517,16 @@ validate_export(nfs_export *exp)
fs_has_fsid) {
if ( !test_export(path, 1)) {
xlog(L_ERROR, "%s does not support NFS export", path);
- return;
+ return 1;
}
} else if ( ! test_export(path, 0)) {
if (test_export(path, 1))
xlog(L_ERROR, "%s requires fsid= for NFS export", path);
else
xlog(L_ERROR, "%s does not support NFS export", path);
- return;
-
+ return 1;
}
+ return 0;
}
static _Bool
--
1.7.12.4
Loading...