cache volume attrs with superblock

This commit is contained in:
U-fast\aglo 2011-06-16 08:05:13 -04:00 committed by unknown
parent a4c726f92d
commit f80d7ec365
4 changed files with 104 additions and 40 deletions

View file

@ -39,11 +39,23 @@ typedef struct __nfs41_superblock {
nfstime4 time_delta; nfstime4 time_delta;
uint64_t maxread; uint64_t maxread;
uint64_t maxwrite; uint64_t maxwrite;
uint32_t layout_types;
bool_t cansettime;
uint32_t aclsupport;
struct list_entry entry; /* position in nfs41_server.superblocks */ struct list_entry entry; /* position in nfs41_server.superblocks */
/* constant filesystem attributes */
unsigned int layout_types : 3;
unsigned int aclsupport : 3;
unsigned int cansettime : 1;
unsigned int link_support : 1;
unsigned int symlink_support : 1;
unsigned int case_preserving : 1;
unsigned int case_insensitive : 1;
/* variable filesystem attributes */
uint64_t space_avail;
uint64_t space_free;
uint64_t space_total;
time_t cache_expiration; /* applies to space_ attributes */
SRWLOCK lock; SRWLOCK lock;
} nfs41_superblock; } nfs41_superblock;
@ -375,6 +387,9 @@ int nfs41_superblock_for_fh(
IN const nfs41_fh *parent OPTIONAL, IN const nfs41_fh *parent OPTIONAL,
OUT nfs41_path_fh *file); OUT nfs41_path_fh *file);
void nfs41_superblock_space_changed(
IN nfs41_superblock *superblock);
void nfs41_superblock_list_init( void nfs41_superblock_list_init(
IN nfs41_superblock_list *superblocks); IN nfs41_superblock_list *superblocks);

View file

@ -426,6 +426,9 @@ int nfs41_open(
&open_res.resok4.deleg_stateid); &open_res.resok4.deleg_stateid);
} }
#endif #endif
if (create == OPEN4_CREATE)
nfs41_superblock_space_changed(state->file.fh.superblock);
out: out:
return status; return status;
} }
@ -607,6 +610,8 @@ int nfs41_create(
file->path->path, &file->name, &file->fh, file->path->path, &file->name, &file->fh,
&file_info, &create_res.cinfo); &file_info, &create_res.cinfo);
ReleaseSRWLockShared(&file->path->lock); ReleaseSRWLockShared(&file->path->lock);
nfs41_superblock_space_changed(file->fh.superblock);
out: out:
return status; return status;
} }
@ -749,6 +754,7 @@ int nfs41_write(
eprintf("WRITE succeeded with count=0; returning %s\n", eprintf("WRITE succeeded with count=0; returning %s\n",
nfs_error_string(status)); nfs_error_string(status));
} }
nfs41_superblock_space_changed(file->fh.superblock);
out: out:
return status; return status;
} }
@ -875,6 +881,7 @@ int nfs41_commit(
nfs41_attr_cache_update(session_name_cache(session), nfs41_attr_cache_update(session_name_cache(session),
file->fh.fileid, &info); file->fh.fileid, &info);
} }
nfs41_superblock_space_changed(file->fh.superblock);
out: out:
return status; return status;
} }
@ -1170,6 +1177,8 @@ int nfs41_remove(
nfs41_name_cache_remove(session_name_cache(session), nfs41_name_cache_remove(session_name_cache(session),
parent->path->path, target, &remove_res.cinfo); parent->path->path, target, &remove_res.cinfo);
ReleaseSRWLockShared(&parent->path->lock); ReleaseSRWLockShared(&parent->path->lock);
nfs41_superblock_space_changed(parent->fh.superblock);
out: out:
return status; return status;
} }
@ -1322,6 +1331,9 @@ int nfs41_setattr(
memcpy(&info->attrmask, &setattr_res.attrsset, sizeof(bitmap4)); memcpy(&info->attrmask, &setattr_res.attrsset, sizeof(bitmap4));
nfs41_attr_cache_update(session_name_cache(session), nfs41_attr_cache_update(session_name_cache(session),
file->fh.fileid, info); file->fh.fileid, info);
if (setattr_res.attrsset.arr[0] & FATTR4_WORD0_SIZE)
nfs41_superblock_space_changed(file->fh.superblock);
out: out:
return status; return status;
} }
@ -1430,6 +1442,8 @@ int nfs41_link(
dst_dir->path->path, target, &link_out->fh, dst_dir->path->path, target, &link_out->fh,
&info[1], &link_res.cinfo); &info[1], &link_res.cinfo);
ReleaseSRWLockShared(&dst_dir->path->lock); ReleaseSRWLockShared(&dst_dir->path->lock);
nfs41_superblock_space_changed(dst_dir->fh.superblock);
out: out:
return status; return status;
} }

View file

@ -82,8 +82,10 @@ static int get_superblock_attrs(
nfs41_file_info info; nfs41_file_info info;
attr_request.arr[0] = FATTR4_WORD0_SUPPORTED_ATTRS | attr_request.arr[0] = FATTR4_WORD0_SUPPORTED_ATTRS |
FATTR4_WORD0_CANSETTIME | FATTR4_WORD0_MAXREAD | FATTR4_WORD0_LINK_SUPPORT | FATTR4_WORD0_SYMLINK_SUPPORT |
(uint32_t)(FATTR4_WORD0_MAXWRITE) | FATTR4_WORD0_ACLSUPPORT; FATTR4_WORD0_ACLSUPPORT | FATTR4_WORD0_CANSETTIME |
FATTR4_WORD0_CASE_INSENSITIVE | FATTR4_WORD0_CASE_PRESERVING |
FATTR4_WORD0_MAXREAD | (uint32_t)(FATTR4_WORD0_MAXWRITE);
attr_request.arr[1] = FATTR4_WORD1_FS_LAYOUT_TYPE | attr_request.arr[1] = FATTR4_WORD1_FS_LAYOUT_TYPE |
FATTR4_WORD1_TIME_DELTA; FATTR4_WORD1_TIME_DELTA;
attr_request.count = 2; attr_request.count = 2;
@ -112,6 +114,11 @@ static int get_superblock_attrs(
superblock->maxwrite = session->fore_chan_attrs.ca_maxrequestsize; superblock->maxwrite = session->fore_chan_attrs.ca_maxrequestsize;
superblock->layout_types = info.fs_layout_types; superblock->layout_types = info.fs_layout_types;
superblock->aclsupport = info.aclsupport;
superblock->link_support = info.link_support;
superblock->symlink_support = info.symlink_support;
superblock->case_preserving = info.case_preserving;
superblock->case_insensitive = info.case_insensitive;
if (bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_CANSETTIME)) if (bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_CANSETTIME))
superblock->cansettime = info.cansettime; superblock->cansettime = info.cansettime;
@ -122,15 +129,18 @@ static int get_superblock_attrs(
if (!bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_TIME_DELTA)) if (!bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_TIME_DELTA))
superblock->time_delta.seconds = 1; superblock->time_delta.seconds = 1;
superblock->aclsupport = info.aclsupport;
dprintf(SBLVL, "attributes for fsid(%llu,%llu): " dprintf(SBLVL, "attributes for fsid(%llu,%llu): "
"maxread=%llu, maxwrite=%llu, layout_types: 0x%X, " "maxread=%llu, maxwrite=%llu, layout_types: 0x%X, "
"cansettime=%u, time_delta={%llu,%u}, aclsupport=%d\n", "cansettime=%u, time_delta={%llu,%u}, aclsupport=%u, "
"link_support=%u, symlink_support=%u, case_preserving=%u, "
"case_insensitive=%u\n",
superblock->fsid.major, superblock->fsid.minor, superblock->fsid.major, superblock->fsid.minor,
superblock->maxread, superblock->maxwrite, superblock->maxread, superblock->maxwrite,
superblock->layout_types, superblock->cansettime, superblock->layout_types, superblock->cansettime,
superblock->time_delta.seconds, superblock->time_delta.nseconds, superblock->time_delta.seconds, superblock->time_delta.nseconds,
superblock->aclsupport); superblock->aclsupport, superblock->link_support,
superblock->symlink_support, superblock->case_preserving,
superblock->case_insensitive);
out: out:
return status; return status;
} }
@ -236,3 +246,12 @@ out:
file->fh.superblock, status); file->fh.superblock, status);
return status; return status;
} }
void nfs41_superblock_space_changed(
IN nfs41_superblock *superblock)
{
/* invalidate cached volume size attributes */
AcquireSRWLockExclusive(&superblock->lock);
superblock->cache_expiration = 0;
ReleaseSRWLockExclusive(&superblock->lock);
}

View file

@ -24,6 +24,7 @@
#include <Windows.h> #include <Windows.h>
#include <strsafe.h> #include <strsafe.h>
#include <stdio.h> #include <stdio.h>
#include <time.h>
#include "nfs41_ops.h" #include "nfs41_ops.h"
#include "from_kernel.h" #include "from_kernel.h"
@ -40,6 +41,8 @@
#define TO_UNITS(bytes) (bytes / BYTES_PER_UNIT) #define TO_UNITS(bytes) (bytes / BYTES_PER_UNIT)
#define VOLUME_CACHE_EXPIRATION 20
/* NFS41_VOLUME_QUERY */ /* NFS41_VOLUME_QUERY */
static int parse_volume(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall) static int parse_volume(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
@ -63,12 +66,29 @@ static int get_volume_size_info(
OUT OPTIONAL PLONGLONG avail_out) OUT OPTIONAL PLONGLONG avail_out)
{ {
nfs41_file_info info = { 0 }; nfs41_file_info info = { 0 };
nfs41_superblock *superblock = state->file.fh.superblock;
int status = ERROR_NOT_FOUND;
AcquireSRWLockShared(&superblock->lock);
/* check superblock for cached attributes */
if (time(NULL) <= superblock->cache_expiration) {
info.space_total = superblock->space_total;
info.space_avail = superblock->space_avail;
info.space_free = superblock->space_free;
status = NO_ERROR;
dprintf(2, "%s cached: %llu user, %llu free of %llu total\n",
query, info.space_avail, info.space_free, info.space_total);
}
ReleaseSRWLockShared(&superblock->lock);
if (status) {
bitmap4 attr_request = { 2, { 0, FATTR4_WORD1_SPACE_AVAIL | bitmap4 attr_request = { 2, { 0, FATTR4_WORD1_SPACE_AVAIL |
FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL } }; FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL } };
int status;
/* query the space_ attributes of the root filesystem */ /* query the space_ attributes of the filesystem */
status = nfs41_getattr(state->session, &state->file, &attr_request, &info); status = nfs41_getattr(state->session, &state->file,
&attr_request, &info);
if (status) { if (status) {
eprintf("nfs41_getattr() failed with %s\n", eprintf("nfs41_getattr() failed with %s\n",
nfs_error_string(status)); nfs_error_string(status));
@ -76,8 +96,16 @@ static int get_volume_size_info(
goto out; goto out;
} }
dprintf(2, "%s: %llu user, %llu free of %llu total\n", query, AcquireSRWLockExclusive(&superblock->lock);
info.space_avail, info.space_free, info.space_total); superblock->space_total = info.space_total;
superblock->space_avail = info.space_avail;
superblock->space_free = info.space_free;
superblock->cache_expiration = time(NULL) + VOLUME_CACHE_EXPIRATION;
ReleaseSRWLockExclusive(&superblock->lock);
dprintf(2, "%s: %llu user, %llu free of %llu total\n",
query, info.space_avail, info.space_free, info.space_total);
}
if (total_out) *total_out = TO_UNITS(info.space_total); if (total_out) *total_out = TO_UNITS(info.space_total);
if (user_out) *user_out = TO_UNITS(info.space_avail); if (user_out) *user_out = TO_UNITS(info.space_avail);
@ -90,32 +118,20 @@ static int handle_volume_attributes(
IN volume_upcall_args *args, IN volume_upcall_args *args,
IN nfs41_open_state *state) IN nfs41_open_state *state)
{ {
/* query the case_ attributes of the root filesystem */
nfs41_file_info info = { 0 };
bitmap4 attr_request = { 1, { FATTR4_WORD0_CASE_INSENSITIVE |
FATTR4_WORD0_CASE_PRESERVING | FATTR4_WORD0_SYMLINK_SUPPORT |
FATTR4_WORD0_LINK_SUPPORT } };
PFILE_FS_ATTRIBUTE_INFORMATION attr = &args->info.attribute; PFILE_FS_ATTRIBUTE_INFORMATION attr = &args->info.attribute;
const nfs41_superblock *superblock = state->file.fh.superblock;
int status = NO_ERROR; int status = NO_ERROR;
status = nfs41_getattr(state->session, &state->file, &attr_request, &info);
if (status) {
eprintf("nfs41_getattr() failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
goto out;
}
attr->FileSystemAttributes = FILE_SUPPORTS_REMOTE_STORAGE; attr->FileSystemAttributes = FILE_SUPPORTS_REMOTE_STORAGE;
if (info.link_support) if (superblock->link_support)
attr->FileSystemAttributes |= FILE_SUPPORTS_HARD_LINKS; attr->FileSystemAttributes |= FILE_SUPPORTS_HARD_LINKS;
if (info.symlink_support) if (superblock->symlink_support)
attr->FileSystemAttributes |= FILE_SUPPORTS_REPARSE_POINTS; attr->FileSystemAttributes |= FILE_SUPPORTS_REPARSE_POINTS;
if (info.case_preserving) if (superblock->case_preserving)
attr->FileSystemAttributes |= FILE_CASE_PRESERVED_NAMES; attr->FileSystemAttributes |= FILE_CASE_PRESERVED_NAMES;
if (!info.case_insensitive) if (!superblock->case_insensitive)
attr->FileSystemAttributes |= FILE_CASE_SENSITIVE_SEARCH; attr->FileSystemAttributes |= FILE_CASE_SENSITIVE_SEARCH;
if (state->file.fh.superblock->aclsupport) if (superblock->aclsupport)
attr->FileSystemAttributes |= FILE_PERSISTENT_ACLS; attr->FileSystemAttributes |= FILE_PERSISTENT_ACLS;
attr->MaximumComponentNameLength = NFS41_MAX_COMPONENT_LEN; attr->MaximumComponentNameLength = NFS41_MAX_COMPONENT_LEN;
@ -126,9 +142,9 @@ static int handle_volume_attributes(
dprintf(2, "FileFsAttributeInformation: case_preserving %u, " dprintf(2, "FileFsAttributeInformation: case_preserving %u, "
"case_insensitive %u, max component %u\n", "case_insensitive %u, max component %u\n",
info.case_preserving, info.case_insensitive, superblock->case_preserving, superblock->case_insensitive,
attr->MaximumComponentNameLength); attr->MaximumComponentNameLength);
out:
return status; return status;
} }