Tuesday, December 03, 2019

Checking/modifying file permissions on an underlying directory

If you have a file system (nfs, etc.) mounted on-top of a directory and you need to see file permissions, ACLs, etc. of the underlying directory and not the mounted fs then:


# mount -F lofs -o nosub /some/path/ /mnt/fix


# mount -B /some/path/ /mnt/fix

If you access /mnt/fix now you won't see any mounted filesystems on top of any directories, just the underlying fs.

I used it in the past and forgot about it, needed it yesterday and found it here.

Monday, October 21, 2019

ONTAP 9.6+: REST API: netapp_ontap: performance of get_collection() vs. get()

NetApp's ONTAP 9.6 introduced new REST API along with a new python module netapp_ontap.


import time
import getpass
import netapp_ontap

from netapp_ontap import config
from netapp_ontap.host_connection import HostConnection
from netapp_ontap.resources import QuotaRule

password = getpass.getpass()

config.CONNECTION = HostConnection(host, user, password)

start = time.time()
quota_rules = QuotaRule.get_collection(fields='type')
# quota_rules = QuotaRule.get_collection()
total = 0
for l in quota_rules:
    # l.get(fields='type')
    total = total + 1
end = time.time()

With 471 quota rules on my filer it takes about 4s with get_collection(fields='type') vs. ~40s when calling l.get(fields='type') for each rule being processed. So if you are after all the entries it is more quicker to pass the required fields to get_collection() and not call get() on each returned resource.

I did a little bit of debugging and it seems that each get() results in a new TCP/HTTPS connection being established which is likely the main reason of the much worse performance performance. Also get_collection() gets all 471 results in a single HTTP GET.

There seems to be a bug in regards to re-ussing connections though, as it shouldn't have to establish a new session for each get.

Thursday, June 13, 2019

DTrace: nfsv4 provider and utf8string

The nfsv4 provider provides some structures with component4 type which is defined as:

typedef struct {
 uint_t utf8string_len;
 char *utf8string_val;
} utf8string;

typedef utf8string component4;

So for example, to print NFSv4 file renames you have to do:

    this->a = (char *)alloca(args[2]->oldname.utf8string_len + 1);
    bcopy(args[2]->oldname.utf8string_val, this->a, args[2]->oldname.utf8string_len);
    this->a[args[2]->oldname.utf8string_len + 1] = '\0';

    this->b = (char *)alloca(args[2]->newname.utf8string_len + 1);
    bcopy(args[2]->newname.utf8string_val, this->b, args[2]->newname.utf8string_len);
    this->b[args[2]->newname.utf8string_len + 1] = '\0';

    printf("NFSv4 rename: %s\n", strjoin(this->a, strjoin(" -> ", this->b)));

Ideally DTrace (strjoin(), etc.) should deal with utf8string type automatically.

Linux Load Averages

Linux measures load average differently than other OS'es. In a nutshell it includes both CPU and disk i/o and more. Brendan has an excellent blog entry on this explaining in much more detail how it works.

Friday, May 03, 2019

Testing ZFS/L2ARC

Solaris 11.4 - setting zfs_arc_collect_check=0 via mdb (takes immediate effect) or via /etc/system makes ZFS to start feeding l2arc immediately. Notice that this can negatively impact ARC performance so use it with care. This is useful for testing if you want to push some data to into L2ARC quicker/sooner, especially on large memory systems. The variable is checked by arc_can_collect() function (if it returns 1 then l2arc cab be fed, if zero it can't).

Monday, March 11, 2019

DTrace stop() action

The stop() action in DTrace stops an entire process... well, actually it doesn't. It stops a single thread in a multi-threaded process, which got me surprised as I always thought it did stop an entire process. Now, this is actually very useful, though a stopall() action which would stop all threads could now be useful as well :)

Update: this is getting more complicated now, the way stop() action behaves depends on probe type it is called from. For example, if called from a probe from syscall provider it will just stop a thread which called the syscall, but if called from a probe from PID provider it will stop entire process with all its threads. This is getting confusing...

btw: pstop PID stops entire process while pstop PID/LWPID stops a single thread

Friday, March 01, 2019

DTrace %Y print format with nanoseconds

Small but useful extension to DTrace is now available in Solaris 11.4.SRU6. It allows to easily print current date with an optional nanosecond resolution. It is disabled by default for backward compatibility.

To enable it you need to add timedecimals option to dtrace:

# dtrace -q -x timedecimals -n syscall::open*:entry \
    '{printf("%Y %s called %s()\n", walltimestamp, execname, probefunc);}'
2019 Mar  1 11:50:48.774114445 firefox called openat64()

2019 Mar  1 11:50:49.149290513 dtrace called openat()
2019 Mar  1 11:50:49.149283375 dtrace called openat()
2019 Mar  1 11:50:50.030217373 firefox called openat64()
2019 Mar  1 11:50:49.974253263 firefox called openat64()

2019 Mar  1 11:50:50.114684381 VBoxService called openat()

You can also specify number of decimal places to be printed, fox example:

# dtrace -q -x timedecimals=2 -n syscall::open*:entry \
    '{printf("%Y %s called %s()\n", walltimestamp, execname, probefunc);}'
2019 Mar  1 11:56:51.09 VBoxService called openat()
2019 Mar  1 11:56:51.09 VBoxService called openat()
2019 Mar  1 11:56:51.45 dtrace called openat()