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;
uint64_t maxread;
uint64_t maxwrite;
uint32_t layout_types;
bool_t cansettime;
uint32_t aclsupport;
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;
} nfs41_superblock;
@ -375,6 +387,9 @@ int nfs41_superblock_for_fh(
IN const nfs41_fh *parent OPTIONAL,
OUT nfs41_path_fh *file);
void nfs41_superblock_space_changed(
IN nfs41_superblock *superblock);
void nfs41_superblock_list_init(
IN nfs41_superblock_list *superblocks);

View file

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

View file

@ -82,8 +82,10 @@ static int get_superblock_attrs(
nfs41_file_info info;
attr_request.arr[0] = FATTR4_WORD0_SUPPORTED_ATTRS |
FATTR4_WORD0_CANSETTIME | FATTR4_WORD0_MAXREAD |
(uint32_t)(FATTR4_WORD0_MAXWRITE) | FATTR4_WORD0_ACLSUPPORT;
FATTR4_WORD0_LINK_SUPPORT | FATTR4_WORD0_SYMLINK_SUPPORT |
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 |
FATTR4_WORD1_TIME_DELTA;
attr_request.count = 2;
@ -112,6 +114,11 @@ static int get_superblock_attrs(
superblock->maxwrite = session->fore_chan_attrs.ca_maxrequestsize;
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))
superblock->cansettime = info.cansettime;
@ -122,15 +129,18 @@ static int get_superblock_attrs(
if (!bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_TIME_DELTA))
superblock->time_delta.seconds = 1;
superblock->aclsupport = info.aclsupport;
dprintf(SBLVL, "attributes for fsid(%llu,%llu): "
"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->maxread, superblock->maxwrite,
superblock->layout_types, superblock->cansettime,
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:
return status;
}
@ -236,3 +246,12 @@ out:
file->fh.superblock, 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 <strsafe.h>
#include <stdio.h>
#include <time.h>
#include "nfs41_ops.h"
#include "from_kernel.h"
@ -40,6 +41,8 @@
#define TO_UNITS(bytes) (bytes / BYTES_PER_UNIT)
#define VOLUME_CACHE_EXPIRATION 20
/* NFS41_VOLUME_QUERY */
static int parse_volume(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
@ -63,21 +66,46 @@ static int get_volume_size_info(
OUT OPTIONAL PLONGLONG avail_out)
{
nfs41_file_info info = { 0 };
bitmap4 attr_request = { 2, { 0, FATTR4_WORD1_SPACE_AVAIL |
FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL } };
int status;
nfs41_superblock *superblock = state->file.fh.superblock;
int status = ERROR_NOT_FOUND;
/* query the space_ attributes of the root filesystem */
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;
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);
dprintf(2, "%s: %llu user, %llu free of %llu total\n", query,
info.space_avail, info.space_free, info.space_total);
if (status) {
bitmap4 attr_request = { 2, { 0, FATTR4_WORD1_SPACE_AVAIL |
FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL } };
/* query the space_ attributes of the filesystem */
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;
}
AcquireSRWLockExclusive(&superblock->lock);
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 (user_out) *user_out = TO_UNITS(info.space_avail);
@ -90,32 +118,20 @@ static int handle_volume_attributes(
IN volume_upcall_args *args,
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;
const nfs41_superblock *superblock = state->file.fh.superblock;
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;
if (info.link_support)
if (superblock->link_support)
attr->FileSystemAttributes |= FILE_SUPPORTS_HARD_LINKS;
if (info.symlink_support)
if (superblock->symlink_support)
attr->FileSystemAttributes |= FILE_SUPPORTS_REPARSE_POINTS;
if (info.case_preserving)
if (superblock->case_preserving)
attr->FileSystemAttributes |= FILE_CASE_PRESERVED_NAMES;
if (!info.case_insensitive)
if (!superblock->case_insensitive)
attr->FileSystemAttributes |= FILE_CASE_SENSITIVE_SEARCH;
if (state->file.fh.superblock->aclsupport)
if (superblock->aclsupport)
attr->FileSystemAttributes |= FILE_PERSISTENT_ACLS;
attr->MaximumComponentNameLength = NFS41_MAX_COMPONENT_LEN;
@ -126,9 +142,9 @@ static int handle_volume_attributes(
dprintf(2, "FileFsAttributeInformation: case_preserving %u, "
"case_insensitive %u, max component %u\n",
info.case_preserving, info.case_insensitive,
superblock->case_preserving, superblock->case_insensitive,
attr->MaximumComponentNameLength);
out:
return status;
}