[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