[SCM] Samba Shared Repository - branch master updated
Christian Ambach
ambi at samba.org
Thu Mar 22 13:15:02 MDT 2012
The branch, master has been updated
via 8718c7b s3:vfs_gpfs: fix some compiler warnings
via 0a37ca5 s3:vfs_gpfs: remove fallback to linux_setlease
via a551ee5 s3:vfs_gpfs: correct use of profiling macros
via 0a89609 s3:vfs_gpfs: Implement fallocate callback for GPFS
via 6261678 s3:vfs_gpfs: Report disk space and usage on GPFS share according to quotas
via a9cfd80 s3:vfs_gpfs: add GPFS api calls for quota and free space reporting
via 4262eb4 s3:vfs_gpfs: Export disk_norm function
via 80cb6e8 s3:client correct a wording
from ffe884c s3: Fix smbd -i
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 8718c7b88de993cef66c2a26ff1addd52b30b05c
Author: Christian Ambach <ambi at samba.org>
Date: Thu Mar 22 18:12:07 2012 +0100
s3:vfs_gpfs: fix some compiler warnings
Autobuild-User: Christian Ambach <ambi at samba.org>
Autobuild-Date: Thu Mar 22 20:14:34 CET 2012 on sn-devel-104
commit 0a37ca5210c8591fc12a6560d3c5fc3ccdeceede
Author: Christian Ambach <ambi at samba.org>
Date: Thu Mar 22 18:11:47 2012 +0100
s3:vfs_gpfs: remove fallback to linux_setlease
if setting the lease in GPFS failed, there is not much sense in trying
to set a lease just locally that would not inform us of openers
on other cluster nodes
commit a551ee5f222264d26e8eb02ecaf90b828433bab8
Author: Christian Ambach <ambi at samba.org>
Date: Thu Mar 22 18:00:17 2012 +0100
s3:vfs_gpfs: correct use of profiling macros
under certain conditions START_PROFILE could have been called, but no END_PROFILE
commit 0a896094c61fa1eec7dbb5bb35485747cdc1549d
Author: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu Mar 8 13:57:12 2012 -0800
s3:vfs_gpfs: Implement fallocate callback for GPFS
GPFS provides the gpfs_prealloc call. Implement the fallocate
callback with mode VFS_FALLOCATE_EXTEND_SIZE using this call.
There is no support for VFS_FALLOCATE_KEEP_SIZE, so report
this mode as not available.
commit 62616784ae5460bfd8f68ccfe596f80f55727b87
Author: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Fri Mar 2 14:26:24 2012 -0700
s3:vfs_gpfs: Report disk space and usage on GPFS share according to quotas
When a client requests the information about free space and space used,
adjust the reported values according to quotas in the GPFS file system:
- Retrieve quotas for the current user, current group and fileset for
the top level of the share.
- If the soft block quota grace time has expired, report disk as full.
- If a hard block quota has been exceeded, report disk as full.
- If none of the hard block quotas been exceeded, report
share size and free space according to the lowest limits found in
the quotas.
- If no applicable hard block quota has been set, report the
information from the statfs call.
This feature is disabled by default and has to be enabled by setting the
option gpfs:dfreequota.
commit a9cfd80d8722f9af7fc18ea70115a6b1b1033168
Author: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Fri Mar 2 14:26:19 2012 -0700
s3:vfs_gpfs: add GPFS api calls for quota and free space reporting
Add the GPFS api calls for reporting the quotas and free space:
- get_gpfs_quota for querying a quota
- get_gpfs_fset_id for mapping a path to a fileset id
commit 4262eb401fac0a6f9f0f76bff390041ad6600536
Author: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Fri Mar 2 14:26:10 2012 -0700
s3:vfs_gpfs: Export disk_norm function
vfs modules implementing the disk_free callback need access
to the function disk_norm for normalizing the data if the parameter
small query is true.
commit 80cb6e84de0fa5c713bf1ba4c5866cdb1aea15f5
Author: Christian Ambach <ambi at samba.org>
Date: Thu Mar 22 16:49:30 2012 +0100
s3:client correct a wording
-----------------------------------------------------------------------
Summary of changes:
docs-xml/manpages-3/vfs_gpfs.8.xml | 72 ++++++++++++++
source3/client/client.c | 2 +-
source3/modules/gpfs.c | 88 +++++++++++++++++
source3/modules/vfs_gpfs.c | 189 +++++++++++++++++++++++++++++++++---
source3/modules/vfs_gpfs.h | 7 +-
source3/smbd/dfree.c | 2 +-
source3/smbd/proto.h | 1 +
7 files changed, 346 insertions(+), 15 deletions(-)
Changeset truncated at 500 lines:
diff --git a/docs-xml/manpages-3/vfs_gpfs.8.xml b/docs-xml/manpages-3/vfs_gpfs.8.xml
index 2107b74..4ea8c4d 100644
--- a/docs-xml/manpages-3/vfs_gpfs.8.xml
+++ b/docs-xml/manpages-3/vfs_gpfs.8.xml
@@ -221,6 +221,78 @@
</varlistentry>
<varlistentry>
+ <term>gpfs:dfreequota = [ yes | no ]</term>
+ <listitem>
+ <para>
+ Adjust reporting of the size and free space of a share
+ according to quotas. If this setting is "yes", a
+ request for size and free space will also evaluate the
+ following quotas:
+ </para>
+
+ <itemizedlist>
+ <listitem><para>The user quota of the user requesting
+ the data.</para></listitem>
+ <listitem><para>The group quota of the primary group
+ of the user.</para></listitem>
+ <listitem><para>The fileset quota for the fileset
+ containing the top level directory of the share.
+ </para></listitem>
+ </itemizedlist>
+
+ <para>
+ If any of the soft or hard quota limits has been
+ reached, the free space will be reported as 0. If a
+ quota is in place, but the limits have not been
+ reached, the free space will be reported according to
+ the space left in the quota. If more than one quota
+ applies the free space will be reported as the smallest
+ space left in those quotas. The size of the share
+ will be reported according to the quota usage. If more
+ than one quota applies, the smallest size will be
+ reported for the share size according to these quotas.
+ </para>
+
+ <itemizedlist>
+ <listitem><para>
+ <command>yes</command> - include the quotas
+ when reporting the share size and free space
+ </para></listitem>
+ <listitem><para>
+ <command>no(default)</command> - do not include quotas,
+ simply report the size and free space of the file system
+ </para></listitem>
+ </itemizedlist>
+ </listitem>
+
+ </varlistentry>
+ <varlistentry>
+
+ <term>gpfs:prealloc = [ yes | no ]</term>
+ <listitem>
+ <para>
+ If set to yes the gpfs_prealloc function will be used in the
+ fallocate callback when appropriate. If set to no gpfs_prealloc
+ will not be used. In both cases the system and libc calls are
+ avoided.
+ </para>
+
+ <itemizedlist>
+ <listitem><para>
+ <command>yes (default)</command> - Use gpfs_prealloc for the
+ fallocate callback.
+ </para></listitem>
+ <listitem><para>
+ <command>no</command> - Do not use gpfs_prealloc for the
+ fallocate callback.
+ </para></listitem>
+ </itemizedlist>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+
<term>nfs4:mode = [ simple | special ]</term>
<listitem>
<para>
diff --git a/source3/client/client.c b/source3/client/client.c
index 9ace7e4..87ec3a9 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -4617,7 +4617,7 @@ static struct {
{"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
{"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
{"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
- {"notify",cmd_notify,"<file>Get notified by dir changes",{COMPL_REMOTE,COMPL_NONE}},
+ {"notify",cmd_notify,"<file>Get notified of dir changes",{COMPL_REMOTE,COMPL_NONE}},
{"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
{"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
{"posix_encrypt",cmd_posix_encrypt,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE,COMPL_NONE}},
diff --git a/source3/modules/gpfs.c b/source3/modules/gpfs.c
index 5ce2381..2cbf0b5 100644
--- a/source3/modules/gpfs.c
+++ b/source3/modules/gpfs.c
@@ -22,6 +22,7 @@
#include "smbd/smbd.h"
#include "libcli/security/security.h"
+#include "gpfs_fcntl.h"
#include "gpfs_gpl.h"
#include "vfs_gpfs.h"
@@ -34,8 +35,12 @@ static int (*gpfs_get_realfilename_path_fn)(char *pathname, char *filenamep,
static int (*gpfs_set_winattrs_path_fn)(char *pathname, int flags, struct gpfs_winattr *attrs);
static int (*gpfs_get_winattrs_path_fn)(char *pathname, struct gpfs_winattr *attrs);
static int (*gpfs_get_winattrs_fn)(int fd, struct gpfs_winattr *attrs);
+static int (*gpfs_prealloc_fn)(int fd, gpfs_off64_t startOffset, gpfs_off64_t bytesToPrealloc);
static int (*gpfs_ftruncate_fn)(int fd, gpfs_off64_t length);
static int (*gpfs_lib_init_fn)(int flags);
+static int (*gpfs_quotactl_fn)(char *pathname, int cmd, int id, void *bufferP);
+static int (*gpfs_fcntl_fn)(gpfs_file_t fileDesc, void *fcntlArgP);
+static int (*gpfs_getfilesetid_fn)(char *pathname, char *name, int *idP);
bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
uint32 share_access)
@@ -173,6 +178,16 @@ int smbd_fget_gpfs_winattrs(int fd, struct gpfs_winattr *attrs)
return gpfs_get_winattrs_fn(fd, attrs);
}
+int smbd_gpfs_prealloc(int fd, gpfs_off64_t start, gpfs_off64_t bytes)
+{
+ if (gpfs_prealloc_fn == NULL) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return gpfs_prealloc_fn(fd, start, bytes);
+}
+
int set_gpfs_winattrs(char *pathname,int flags,struct gpfs_winattr *attrs)
{
if (gpfs_set_winattrs_path_fn == NULL) {
@@ -184,6 +199,75 @@ int set_gpfs_winattrs(char *pathname,int flags,struct gpfs_winattr *attrs)
return gpfs_set_winattrs_path_fn(pathname,flags, attrs);
}
+int get_gpfs_quota(const char *pathname, int type, int id,
+ struct gpfs_quotaInfo *qi)
+{
+ int ret;
+
+ if (!gpfs_quotactl_fn) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ ZERO_STRUCTP(qi);
+ ret = gpfs_quotactl_fn(discard_const_p(char, pathname),
+ GPFS_QCMD(Q_GETQUOTA, type), id, qi);
+
+ if (ret) {
+ if (errno == GPFS_E_NO_QUOTA_INST) {
+ DEBUG(10, ("Quotas disabled on GPFS filesystem.\n"));
+ } else {
+ DEBUG(0, ("Get quota failed, type %d, id, %d, "
+ "errno %d.\n", type, id, errno));
+ }
+
+ return ret;
+ }
+
+ DEBUG(10, ("quota type %d, id %d, blk u:%lld h:%lld s:%lld gt:%u\n",
+ type, id, qi->blockUsage, qi->blockHardLimit,
+ qi->blockSoftLimit, qi->blockGraceTime));
+
+ return ret;
+}
+
+int get_gpfs_fset_id(const char *pathname, int *fset_id)
+{
+ int err, fd, errno_fcntl;
+
+ struct {
+ gpfsFcntlHeader_t hdr;
+ gpfsGetFilesetName_t fsn;
+ } arg;
+
+ if (!gpfs_fcntl_fn || !gpfs_getfilesetid_fn) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ arg.hdr.totalLength = sizeof(arg);
+ arg.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
+ arg.hdr.fcntlReserved = 0;
+ arg.fsn.structLen = sizeof(arg.fsn);
+ arg.fsn.structType = GPFS_FCNTL_GET_FILESETNAME;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd == -1)
+ return fd;
+
+ err = gpfs_fcntl_fn(fd, &arg);
+ errno_fcntl = errno;
+ close(fd);
+
+ if (err) {
+ errno = errno_fcntl;
+ return err;
+ }
+
+ return gpfs_getfilesetid_fn(discard_const_p(char, pathname),
+ arg.fsn.buffer, fset_id);
+}
+
void smbd_gpfs_lib_init()
{
if (gpfs_lib_init_fn) {
@@ -256,8 +340,12 @@ void init_gpfs(void)
init_gpfs_function(&gpfs_get_winattrs_path_fn,"gpfs_get_winattrs_path");
init_gpfs_function(&gpfs_set_winattrs_path_fn,"gpfs_set_winattrs_path");
init_gpfs_function(&gpfs_get_winattrs_fn,"gpfs_get_winattrs");
+ init_gpfs_function(&gpfs_prealloc_fn, "gpfs_prealloc");
init_gpfs_function(&gpfs_ftruncate_fn, "gpfs_ftruncate");
init_gpfs_function(&gpfs_lib_init_fn,"gpfs_lib_init");
+ init_gpfs_function(&gpfs_quotactl_fn, "gpfs_quotactl");
+ init_gpfs_function(&gpfs_fcntl_fn, "gpfs_fcntl");
+ init_gpfs_function(&gpfs_getfilesetid_fn, "gpfs_getfilesetid");
return;
}
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 6a9d3d5..fce1b28 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -33,6 +33,7 @@
#include "nfs4_acls.h"
#include "vfs_gpfs.h"
#include "system/filesys.h"
+#include "auth.h"
struct gpfs_config_data {
bool sharemodes;
@@ -42,6 +43,8 @@ struct gpfs_config_data {
bool winattr;
bool ftruncate;
bool getrealfilename;
+ bool dfreequota;
+ bool prealloc;
};
@@ -50,6 +53,7 @@ static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
{
struct gpfs_config_data *config;
+ int ret = 0;
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct gpfs_config_data,
@@ -61,12 +65,12 @@ static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
if (config->sharemodes
&& !set_gpfs_sharemode(fsp, access_mask, fsp->share_access)) {
- return -1;
+ ret = -1;
}
END_PROFILE(syscall_kernel_flock);
- return 0;
+ return ret;
}
static int vfs_gpfs_close(vfs_handle_struct *handle, files_struct *fsp)
@@ -95,21 +99,15 @@ static int vfs_gpfs_setlease(vfs_handle_struct *handle, files_struct *fsp,
struct gpfs_config_data,
return -1);
- START_PROFILE(syscall_linux_setlease);
-
if (linux_set_lease_sighandler(fsp->fh->fd) == -1)
return -1;
+ START_PROFILE(syscall_linux_setlease);
+
if (config->leases) {
ret = set_gpfs_lease(fsp->fh->fd,leasetype);
}
- if (ret < 0) {
- /* This must have come from GPFS not being available */
- /* or some other error, hence call the default */
- ret = linux_setlease(fsp->fh->fd, leasetype);
- }
-
END_PROFILE(syscall_linux_setlease);
return ret;
@@ -1261,6 +1259,42 @@ static int vfs_gpfs_ntimes(struct vfs_handle_struct *handle,
}
+static int vfs_gpfs_fallocate(struct vfs_handle_struct *handle,
+ struct files_struct *fsp, enum vfs_fallocate_mode mode,
+ SMB_OFF_T offset, SMB_OFF_T len)
+{
+ int ret;
+ struct gpfs_config_data *config;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, config,
+ struct gpfs_config_data,
+ return -1);
+
+ if (!config->prealloc) {
+ /* you should better not run fallocate() on GPFS at all */
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ if (mode == VFS_FALLOCATE_KEEP_SIZE) {
+ DEBUG(10, ("Unsupported VFS_FALLOCATE_KEEP_SIZE\n"));
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ ret = smbd_gpfs_prealloc(fsp->fh->fd, offset, len);
+
+ if (ret == -1 && errno != ENOSYS) {
+ DEBUG(0, ("GPFS prealloc failed: %s\n", strerror(errno)));
+ } else if (ret == -1 && errno == ENOSYS) {
+ DEBUG(10, ("GPFS prealloc not supported.\n"));
+ } else {
+ DEBUG(10, ("GPFS prealloc succeeded.\n"));
+ }
+
+ return ret;
+}
+
static int vfs_gpfs_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
SMB_OFF_T len)
{
@@ -1343,8 +1377,8 @@ static ssize_t vfs_gpfs_sendfile(vfs_handle_struct *handle, int tofd,
return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, hdr, offset, n);
}
-int vfs_gpfs_connect(struct vfs_handle_struct *handle, const char *service,
- const char *user)
+static int vfs_gpfs_connect(struct vfs_handle_struct *handle,
+ const char *service, const char *user)
{
struct gpfs_config_data *config;
int ret;
@@ -1385,6 +1419,12 @@ int vfs_gpfs_connect(struct vfs_handle_struct *handle, const char *service,
config->getrealfilename = lp_parm_bool(SNUM(handle->conn), "gpfs",
"getrealfilename", true);
+ config->dfreequota = lp_parm_bool(SNUM(handle->conn), "gpfs",
+ "dfreequota", false);
+
+ config->prealloc = lp_parm_bool(SNUM(handle->conn), "gpfs",
+ "prealloc", true);
+
SMB_VFS_HANDLE_SET_DATA(handle, config,
NULL, struct gpfs_config_data,
return -1);
@@ -1392,6 +1432,129 @@ int vfs_gpfs_connect(struct vfs_handle_struct *handle, const char *service,
return 0;
}
+static int vfs_gpfs_get_quotas(const char *path, uid_t uid, gid_t gid,
+ int *fset_id,
+ struct gpfs_quotaInfo *qi_user,
+ struct gpfs_quotaInfo *qi_group,
+ struct gpfs_quotaInfo *qi_fset)
+{
+ int err;
+
+ err = get_gpfs_fset_id(path, fset_id);
+ if (err) {
+ DEBUG(0, ("Get fset id failed, errno %d.\n", errno));
+ return err;
+ }
+
+ err = get_gpfs_quota(path, GPFS_USRQUOTA, uid, qi_user);
+ if (err) {
+ return err;
+ }
+
+ err = get_gpfs_quota(path, GPFS_GRPQUOTA, gid, qi_group);
+ if (err) {
+ return err;
+ }
+
+ err = get_gpfs_quota(path, GPFS_FILESETQUOTA, *fset_id, qi_fset);
+ if (err) {
+ return err;
+ }
+
+ return 0;
+}
+
+static void vfs_gpfs_disk_free_quota(struct gpfs_quotaInfo qi, time_t cur_time,
+ uint64_t *dfree, uint64_t *dsize)
+{
+ uint64_t usage, limit;
+
+ /*
+ * The quota reporting is done in units of 1024 byte blocks, but
+ * sys_fsusage uses units of 512 byte blocks, adjust the block number
+ * accordingly. Also filter possibly negative usage counts from gpfs.
+ */
+ usage = qi.blockUsage < 0 ? 0 : (uint64_t)qi.blockUsage * 2;
+ limit = (uint64_t)qi.blockHardLimit * 2;
+
+ /*
+ * When the grace time for the exceeded soft block quota has been
+ * exceeded, the soft block quota becomes an additional hard limit.
+ */
+ if (qi.blockGraceTime && cur_time > qi.blockGraceTime) {
+ /* report disk as full */
+ *dfree = 0;
+ *dsize = MIN(*dsize, usage);
+ }
+
+ if (!qi.blockHardLimit)
+ return;
+
+ if (usage >= limit) {
+ /* report disk as full */
+ *dfree = 0;
+ *dsize = MIN(*dsize, usage);
+
+ } else {
+ /* limit has not been reached, determine "free space" */
+ *dfree = MIN(*dfree, limit - usage);
+ *dsize = MIN(*dsize, limit);
+ }
+}
+
+static uint64_t vfs_gpfs_disk_free(vfs_handle_struct *handle, const char *path,
+ bool small_query, uint64_t *bsize,
+ uint64_t *dfree, uint64_t *dsize)
+{
+ struct security_unix_token *utok;
+ struct gpfs_quotaInfo qi_user, qi_group, qi_fset;
+ struct gpfs_config_data *config;
+ int err, fset_id;
+ time_t cur_time;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, config, struct gpfs_config_data,
+ return (uint64_t)-1);
+ if (!config->dfreequota) {
+ return SMB_VFS_NEXT_DISK_FREE(handle, path, small_query,
+ bsize, dfree, dsize);
+ }
+
+ err = sys_fsusage(path, dfree, dsize);
+ if (err) {
+ DEBUG (0, ("Could not get fs usage, errno %d\n", errno));
+ return SMB_VFS_NEXT_DISK_FREE(handle, path, small_query,
+ bsize, dfree, dsize);
+ }
+
+ /* sys_fsusage returns units of 512 bytes */
+ *bsize = 512;
+
+ DEBUG(10, ("fs dfree %llu, dsize %llu\n",
+ (unsigned long long)*dfree, (unsigned long long)*dsize));
+
+ utok = handle->conn->session_info->unix_token;
+ err = vfs_gpfs_get_quotas(path, utok->uid, utok->gid, &fset_id,
+ &qi_user, &qi_group, &qi_fset);
+ if (err) {
+ return SMB_VFS_NEXT_DISK_FREE(handle, path, small_query,
+ bsize, dfree, dsize);
+ }
+
+ cur_time = time(NULL);
+
+ /* Adjust free space and size according to quota limits. */
+ vfs_gpfs_disk_free_quota(qi_user, cur_time, dfree, dsize);
+ vfs_gpfs_disk_free_quota(qi_group, cur_time, dfree, dsize);
+
+ /* Id 0 indicates the default quota, not an actual quota */
+ if (fset_id != 0) {
+ vfs_gpfs_disk_free_quota(qi_fset, cur_time, dfree, dsize);
+ }
+
+ disk_norm(small_query, bsize, dfree, dsize);
+ return *dfree;
+}
+
static uint32_t vfs_gpfs_capabilities(struct vfs_handle_struct *handle,
enum timestamp_set_resolution *p_ts_res)
{
@@ -1429,6 +1592,7 @@ static int vfs_gpfs_open(struct vfs_handle_struct *handle,
static struct vfs_fn_pointers vfs_gpfs_fns = {
.connect_fn = vfs_gpfs_connect,
+ .disk_free_fn = vfs_gpfs_disk_free,
.fs_capabilities_fn = vfs_gpfs_capabilities,
.kernel_flock_fn = vfs_gpfs_kernel_flock,
.linux_setlease_fn = vfs_gpfs_setlease,
--
Samba Shared Repository
More information about the samba-cvs
mailing list