Do -[NSURL removeCachedResourceValueForKey:] and -[NSURL removeAllCachedResourceValues] clear the cached information in this case? It doesn't seem that they do.

Scott

On Mon, 3 Apr 2017, Scott Talbert wrote:

It sure sounds that way. However, I haven't been able to spot a problem in the FUSE kext thus far. It seems to be setting VOL_CAP_FMT_2TB_FILESIZE when it should be.

On Mon, 3 Apr 2017, Jim Luther wrote:


      On Apr 3, 2017, at 8:56 AM, Scott Talbert <s...@techie.net>
      wrote:

It's getting a value from the getattrlist path.

The fact that the data is cached at mount time is an interesting
clue. It suggest that perhaps there may be some window just shortly
after mount that the incorrect data is getting reported and cached.

It's a FUSE filesystem.  However, some of the more commonly-used FUSE
filesystems (e.g., sshfs) seem to behave the same way.


That sounds like a bug in FUSE. Once a file system is mounted, the kernel
sends out a VQ_MOUNT kernel event and that's what causes the
kNotifyVFSMount BSD notification to be sent. At that time, file systems
must be ready to respond to requests correctly. If they don't, they have a
bug.

- Jim

      On Sat, 1 Apr 2017, Jim Luther wrote:

            Scott, if you walk through that code, do you see
            which path it's getting a value from -- pathconf or
            getattrlist?

            The code in our frameworks that gets that value
            runs when a file system is first mounted. We have
            code listening for kNotifyVFSMount BSD
            notifications. When a notification comes in, we
            look to see what new volume(s) are available, and
            then collect and cache the volume's immutable
            properties (like this capability).

            Knowing more about the file system (what file
            system type, how it's connected, etc) where you are
            seeing the problem might help diagnose things.

            - Jim

                  On Mar 31, 2017, at 5:10 PM, Scott
                  Talbert <s...@techie.net> wrote:

                  Thanks for the information.
                   Unfortunately, that leaves me even
                  more
                  confused as, using that code, I get the
                  correct answer:

                  #include <sys/attr.h>
                  #include <sys/param.h>
                  #include <sys/mount.h>
                  #import <Foundation/Foundation.h>

                  int getMaxFileSize(const char *path,
                  int64_t *maxFileSize)
                  {
                    int result;
                    struct statfs statfsBuf;


                    // get the file system's mount point
                  path for the input path
                    result = statfs(path, &statfsBuf);
                    if ( result == 0 ) {
                        long fileSizeBits =
                  pathconf(statfsBuf.f_mntonname,
                  _PC_FILESIZEBITS);
                        if (fileSizeBits == -1) {
                            // if _PC_FILESIZEBITS isn't
                  supported, check for
                  VOL_CAP_FMT_2TB_FILESIZE
                            bool
                  fileSystemSupports2TBFileSize = false;


                            // get the supported
                  capabilities
                            struct attrlist attrList;
                            struct volCapabilitiesBuf {
                                u_int32_t length;
                                vol_capabilities_attr_t
                  capabilities;
                            } __attribute__((aligned(4),
                  packed));
                            struct volCapabilitiesBuf
                  volCaps;


                            memset(&attrList, 0,
                  sizeof(attrList));
                            attrList.bitmapcount =
                  ATTR_BIT_MAP_COUNT;
                            attrList.volattr =
                  ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES;
                            result =
                  getattrlist(statfsBuf.f_mntonname,
                  &attrList,
                  &volCaps, sizeof(volCaps), 0);
                            if ( result == 0 ) {
                                fileSystemSupports2TBFileSize
                  =
                  ((volCaps.capabilities.capabilities[VOL_CAPABILITIES_FORMAT]
                  & VOL_CAP_FMT_2TB_FILESIZE) &&
                  (volCaps.capabilities.valid[VOL_CAPABILITIES_FORMAT]
                  &
                  VOL_CAP_FMT_2TB_FILESIZE));
                            }


                            if (
                  fileSystemSupports2TBFileSize ) {
                                // use
                  Supports2TBFileSize
                                *maxFileSize =
                  LONG_LONG_MAX;
                            }
                            else {
                                // otherwise, we don't
                  know
                                *maxFileSize = -1LL;
                            }
                        }
                        else if ( fileSizeBits > 64 ) {
                            // off_t is signed long long,
                  so it cannot be more than
                  LONG_LONG_MAX
                            *maxFileSize = LONG_LONG_MAX;
                        }
                        else if ( fileSizeBits < 32 ) {
                            // POSIX spec says 'Minimum
                  Acceptable Value: 32' for
                  FILESIZEBITS
                            *maxFileSize = INT_MAX;
                        }
                        else {
                            // 32...64 bits: shift off
                  the bits we don't need
                            *maxFileSize =
                  (int64_t)((u_int64_t)0xffffffffffffffffLL
                  >>
                  (u_int64_t)(65 - fileSizeBits));
                        }
                    }
                    return result;
                  }

                  int main()
                  {
                  const char *mount =
                  "/Volumes/Filesystem";

                  int64_t maxFileSize;
                  int ret1 = getMaxFileSize(mount,
                  &maxFileSize);
                  NSLog(@"getMaxFileSize %d %lld", ret1,
                  maxFileSize);

                  NSString *path = [NSString
                  stringWithUTF8String:mount];
                  NSURL *url = [NSURL
                  fileURLWithPath:path];
                  NSNumber *maxfilesize;
                  NSError *error;
                  BOOL ret = [url
                  getResourceValue:&maxfilesize
                  forKey:NSURLVolumeMaximumFileSizeKey
                  error:&error];
                  NSLog(@"NSURLVolumeMaximumFileSize: %d
                  %@ %@", ret, maxfilesize, error);

                  }

                  $ ./blahm
                  2017-03-31 20:04:34.358
                  blahm[45735:2028260] getMaxFileSize 0
                  9223372036854775807
                  2017-03-31 20:04:34.365
                  blahm[45735:2028260]
                  NSURLVolumeMaximumFileSize: 1
                  (null) (null)

                        As -[NSURL
                        getResourceValue:forKey:error:]
                        is documented, "If this
                        method
                        returns YES and the value
                        is populated with nil, it
                        means that the
                        resource property is not
                        available for the specified
                        resource, and that no
                        errors occurred when
                        determining that the
                        resource property was
                        unavailable." So YES and
                        nil is a valid response.

                        The
                        NSURLVolumeMaximumFileSizeKey
                        property value comes from
                        two sources:
                        pathconf() with
                        _PC_FILESIZEBITS, or from
                        getattrlist() from the
                        ATTR_VOL_CAPABILITIES
                        attribute and the
                        VOL_CAP_FMT_2TB_FILESIZE
                        capability.

                        Here's code (not the real
                        code but the exact same
                        algorithm) that shows
                        how the value is
                        calculated:

                        int getMaxFileSize(const
                        char *path, int64_t
                        *maxFileSize)
                        {
                          int result;
                          struct statfs statfsBuf;

                          // get the file system's
                        mount point path for the
                        input path
                          result = statfs(path,
                        &statfsBuf);
                          if ( result == 0 ) {
                              long fileSizeBits =
                        pathconf(statfsBuf.f_mntonname,
                        _PC_FILESIZEBITS);
                              if (fileSizeBits ==
                        -1) {
                                  // if
                        _PC_FILESIZEBITS isn't
                        supported, check for
                        VOL_CAP_FMT_2TB_FILESIZE
                                  bool
                        fileSystemSupports2TBFileSize
                        = false;

                                  // get the
                        supported capabilities
                                  struct attrlist
                        attrList;
                                  struct
                        volCapabilitiesBuf {
                                      u_int32_t
                        length;
                                      vol_capabilities_attr_t
                        capabilities;
                                  }
                        __attribute__((aligned(4),
                        packed));
                                  struct
                        volCapabilitiesBuf volCaps;

                                  memset(&attrList,
                        0, sizeof(attrList));
                                  attrList.bitmapcount
                        = ATTR_BIT_MAP_COUNT;
                                  attrList.volattr
                        = ATTR_VOL_INFO |
                        ATTR_VOL_CAPABILITIES;
                                  result =
                        getattrlist(statfsBuf.f_mntonname,
                        &attrList,
                        &volCaps, sizeof(volCaps),
                        0);
                                  if ( result == 0
                        ) {
                                      fileSystemSupports2TBFileSize
                        =
                        
((volCaps.capabilities.capabilities[VOL_CAPABILITIES_FORMAT]
                        & VOL_CAP_FMT_2TB_FILESIZE)
                        &&
                        (volCaps.capabilities.valid[VOL_CAPABILITIES_FORMAT]
                        &
                        VOL_CAP_FMT_2TB_FILESIZE));
                                  }

                                  if (
                        fileSystemSupports2TBFileSize
                        ) {
                                      // use
                        Supports2TBFileSize
                                      *maxFileSize
                        = LONG_LONG_MAX;
                                  }
                                  else {
                                      // otherwise,
                        we don't know
                                      *maxFileSize
                        = -1LL;
                                  }
                              }
                              else if (
                        fileSizeBits > 64 ) {
                                  // off_t is
                        signed long long, so it
                        cannot be more than
                        LONG_LONG_MAX
                                  *maxFileSize =
                        LONG_LONG_MAX;
                              }
                              else if (
                        fileSizeBits < 32 ) {
                                  // POSIX spec
                        says 'Minimum Acceptable
                        Value: 32' for
                        FILESIZEBITS
                                  *maxFileSize =
                        INT_MAX;
                              }
                              else {
                                  // 32...64 bits:
                        shift off the bits we don't
                        need
                                  *maxFileSize =
                        (int64_t)((u_int64_t)0xffffffffffffffffLL
                        >>
                        (u_int64_t)(65 -
                        fileSizeBits));
                              }
                          }
                          return result;
                        }

                        if
                        NSURLVolumeMaximumFileSizeKey
                        is returning nil with no
                        errors,
                        maxFileSize is -1LL, and
                        the only way maxFileSize
                        will be -1LL is if
                        pathconf() returned an
                        error, and the file system
                        is saying
                        VOL_CAP_FMT_2TB_FILESIZE is
                        not valid and set
                        (capabilities).

                        Hope that helpsâ?¢

                        - Jim

                              On Mar 31,
                              2017, at 2:33
                              PM, Scott
                              Talbert
                              <s...@techie.net>
                              wrote:

                              Hello,

                              Can anyone tell
                              me why calling
                              NSURL
                              -getResourceValue:forKey:error:
                              with key
                              NSURLVolumeMaximumFileSizeKey
                              would return a
                              nil resource
                              value
                              for a given
                              volume?  The
                              function
                              returns YES and
                              error is nil
                              also.

                              I can see from
                              running dtruss
                              that it in turn
                              calls
                              getattrlist().
                               If I
                              call
                              getattrlist()
                              myself on the
                              same volume, I
                              can see the
                              bits I would
                              think it is
                              looking at are
                              set correctly -
                              VOL_CAP_FMT_2TB_FILESIZE.

                              Thanks,
                              Scott
                              _______________________________________________
                              Do not post
                              admin requests
                              to the list.
                              They will be
                              ignored.
                              Filesystem-dev
                              mailing list
                                   (Filesystem-dev@lists.apple.com)
                              Help/Unsubscribe/Update
                              your
                              Subscription:
https://lists.apple.com/mailman/options/filesystem-dev/luther.j%40apple.co
                              m

                              This email sent
                              to
                              luthe...@apple.com










 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Filesystem-dev mailing list      (Filesystem-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/filesystem-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to