| diff --git a/Makefile.am b/Makefile.am |
| index ae7cd16..c9e9f87 100644 |
| --- a/Makefile.am |
| +++ b/Makefile.am |
| @@ -2,7 +2,7 @@ |
| |
| AUTOMAKE_OPTIONS = foreign |
| |
| -SUBDIRS = tools support utils linux-nfs tests |
| +SUBDIRS = tools support utils linux-nfs tests systemd |
| |
| MAINTAINERCLEANFILES = Makefile.in |
| |
| diff --git a/configure.ac b/configure.ac |
| index 7b93de6..4ee4db5 100644 |
| --- a/configure.ac |
| +++ b/configure.ac |
| @@ -54,6 +54,16 @@ AC_ARG_WITH(start-statd, |
| ) |
| AC_SUBST(startstatd) |
| AC_DEFINE_UNQUOTED(START_STATD, "$startstatd", [Define this to a script which can start statd on mount]) |
| +unitdir=/usr/lib/systemd/system |
| +AC_ARG_WITH(systemd, |
| + [AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@], |
| + [install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])], |
| + test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1 |
| + use_systemd=0 |
| + ) |
| + AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1]) |
| + AC_SUBST(unitdir) |
| + |
| AC_ARG_ENABLE(nfsv4, |
| [AC_HELP_STRING([--enable-nfsv4], |
| [enable support for NFSv4 @<:@default=yes@:>@])], |
| @@ -506,6 +516,7 @@ AC_CONFIG_FILES([ |
| utils/showmount/Makefile |
| utils/statd/Makefile |
| utils/osd_login/Makefile |
| + systemd/Makefile |
| tests/Makefile |
| tests/nsm_client/Makefile]) |
| AC_OUTPUT |
| diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h |
| index 2f59e6a..1194255 100644 |
| --- a/support/include/nfs/export.h |
| +++ b/support/include/nfs/export.h |
| @@ -26,6 +26,7 @@ |
| #define NFSEXP_CROSSMOUNT 0x4000 |
| #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ |
| #define NFSEXP_V4ROOT 0x10000 |
| +#define NFSEXP_PNFS 0x20000 |
| /* |
| * All flags supported by the kernel before addition of the |
| * export_features interface: |
| diff --git a/support/nfs/exports.c b/support/nfs/exports.c |
| index 5451ed7..9399a12 100644 |
| --- a/support/nfs/exports.c |
| +++ b/support/nfs/exports.c |
| @@ -275,6 +275,7 @@ putexportent(struct exportent *ep) |
| "no_" : ""); |
| if (ep->e_flags & NFSEXP_NOREADDIRPLUS) |
| fprintf(fp, "nordirplus,"); |
| + fprintf(fp, "%spnfs,", (ep->e_flags & NFSEXP_PNFS)? "" : "no_"); |
| if (ep->e_flags & NFSEXP_FSID) { |
| fprintf(fp, "fsid=%d,", ep->e_fsid); |
| } |
| @@ -581,6 +582,10 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr) |
| clearflags(NFSEXP_NOACL, active, ep); |
| else if (strcmp(opt, "no_acl") == 0) |
| setflags(NFSEXP_NOACL, active, ep); |
| + else if (!strcmp(opt, "pnfs")) |
| + setflags(NFSEXP_PNFS, active, ep); |
| + else if (!strcmp(opt, "no_pnfs")) |
| + clearflags(NFSEXP_PNFS, active, ep); |
| else if (strncmp(opt, "anonuid=", 8) == 0) { |
| char *oe; |
| ep->e_anonuid = strtol(opt+8, &oe, 10); |
| diff --git a/systemd/Makefile.am b/systemd/Makefile.am |
| new file mode 100644 |
| index 0000000..fbcabb1 |
| --- /dev/null |
| +++ b/systemd/Makefile.am |
| @@ -0,0 +1,31 @@ |
| +## Process this file with automake to produce Makefile.in |
| + |
| +MAINTAINERCLEANFILES = Makefile.in |
| + |
| +unit_files = \ |
| + nfs-client.target \ |
| + \ |
| + auth-rpcgss-module.service \ |
| + nfs-blkmap.service \ |
| + nfs-config.service \ |
| + nfs-idmapd.service \ |
| + nfs-mountd.service \ |
| + nfs-server.service \ |
| + nfs-utils.service \ |
| + rpc-gssd.service \ |
| + rpc-statd-notify.service \ |
| + rpc-statd.service \ |
| + rpc-svcgssd.service \ |
| + \ |
| + proc-fs-nfsd.mount \ |
| + var-lib-nfs-rpc_pipefs.mount |
| + |
| +EXTRA_DIST = $(unit_files) |
| + |
| +unit_dir = /usr/lib/systemd/system |
| + |
| +if INSTALL_SYSTEMD |
| +install-data-hook: $(unit_files) |
| + mkdir -p $(DESTDIR)/$(unitdir) |
| + cp $(unit_files) $(DESTDIR)/$(unitdir) |
| +endif |
| diff --git a/systemd/README b/systemd/README |
| index a2a5f06..bbd7790 100644 |
| --- a/systemd/README |
| +++ b/systemd/README |
| @@ -24,7 +24,7 @@ by a suitable 'preset' setting: |
| is started by /usr/sbin/start-statd which mount.nfs will run |
| if statd is needed. |
| |
| - nfs-blkmap.target |
| + nfs-blkmap.service |
| If enabled, then blkmapd will be run when nfs-client.target is |
| started. |
| |
| diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service |
| index f470e3d..ddbf4e9 100644 |
| --- a/systemd/nfs-blkmap.service |
| +++ b/systemd/nfs-blkmap.service |
| @@ -5,12 +5,13 @@ Conflicts=umount.target |
| After=var-lib-nfs-rpc_pipefs.mount |
| Requires=var-lib-nfs-rpc_pipefs.mount |
| |
| -Requisite=nfs-blkmap.target |
| -After=nfs-blkmap.target |
| - |
| PartOf=nfs-utils.service |
| |
| [Service] |
| Type=forking |
| PIDFile=/var/run/blkmapd.pid |
| +EnvironmentFile=-/run/sysconfig/nfs-utils |
| ExecStart=/usr/sbin/blkmapd $BLKMAPDARGS |
| + |
| +[Install] |
| +WantedBy=nfs-client.target |
| diff --git a/systemd/nfs-blkmap.target b/systemd/nfs-blkmap.target |
| deleted file mode 100644 |
| index fbcc111..0000000 |
| --- a/systemd/nfs-blkmap.target |
| +++ /dev/null |
| @@ -1,8 +0,0 @@ |
| -[Unit] |
| -Description= PNFS blkmaping enablement. |
| -# If this target is enabled, then blkmapd will be started |
| -# as required. If it is not enabled it won't. |
| - |
| -[Install] |
| -WantedBy=remote-fs.target |
| -WantedBy=multi-user.target |
| \ No newline at end of file |
| diff --git a/systemd/nfs-client.target b/systemd/nfs-client.target |
| index 9b792a3..8a8300a 100644 |
| --- a/systemd/nfs-client.target |
| +++ b/systemd/nfs-client.target |
| @@ -5,8 +5,7 @@ Wants=remote-fs-pre.target |
| |
| # Note: we don't "Wants=rpc-statd.service" as "mount.nfs" will arrange to |
| # start that on demand if needed. |
| -Wants=nfs-blkmap.service rpc-statd-notify.service |
| -After=nfs-blkmap.service |
| +Wants=rpc-statd-notify.service |
| |
| # GSS services dependencies and ordering |
| Wants=auth-rpcgss-module.service |
| diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c |
| index df4627e..b52afe2 100644 |
| --- a/utils/blkmapd/device-discovery.c |
| +++ b/utils/blkmapd/device-discovery.c |
| @@ -77,16 +77,6 @@ struct bl_disk_path *bl_get_path(const char *filepath, |
| return tmp; |
| } |
| |
| -/* Check whether valid_path is a substring(partition) of path */ |
| -int bl_is_partition(struct bl_disk_path *valid_path, struct bl_disk_path *path) |
| -{ |
| - if (!strncmp(valid_path->full_path, path->full_path, |
| - strlen(valid_path->full_path))) |
| - return 1; |
| - |
| - return 0; |
| -} |
| - |
| /* |
| * For multipath devices, devices state could be PASSIVE/ACTIVE/PSEUDO, |
| * where PSEUDO > ACTIVE > PASSIVE. Device with highest state is used to |
| @@ -95,19 +85,13 @@ int bl_is_partition(struct bl_disk_path *valid_path, struct bl_disk_path *path) |
| * If device-mapper multipath support is a must, pseudo devices should |
| * exist for each multipath device. If not, active device path will be |
| * chosen for device creation. |
| - * Treat partition as invalid path. |
| */ |
| -int bl_update_path(struct bl_disk_path *path, enum bl_path_state_e state, |
| - struct bl_disk *disk) |
| +int bl_update_path(enum bl_path_state_e state, struct bl_disk *disk) |
| { |
| struct bl_disk_path *valid_path = disk->valid_path; |
| |
| - if (valid_path) { |
| - if (valid_path->state >= state) { |
| - if (bl_is_partition(valid_path, path)) |
| - return 0; |
| - } |
| - } |
| + if (valid_path && valid_path->state >= state) |
| + return 0; |
| return 1; |
| } |
| |
| @@ -164,15 +148,16 @@ void bl_add_disk(char *filepath) |
| |
| dev = sb.st_rdev; |
| serial = bldev_read_serial(fd, filepath); |
| - if (dm_is_dm_major(major(dev))) |
| + if (!serial) { |
| + BL_LOG_ERR("%s: no serial found for %s\n", |
| + __func__, filepath); |
| + ap_state = BL_PATH_STATE_PASSIVE; |
| + } else if (dm_is_dm_major(major(dev))) |
| ap_state = BL_PATH_STATE_PSEUDO; |
| else |
| ap_state = bldev_read_ap_state(fd); |
| close(fd); |
| |
| - if (ap_state != BL_PATH_STATE_ACTIVE) |
| - return; |
| - |
| for (disk = visible_disk_list; disk != NULL; disk = disk->next) { |
| /* Already scanned or a partition? |
| * XXX: if released each time, maybe not need to compare |
| @@ -216,7 +201,7 @@ void bl_add_disk(char *filepath) |
| path->next = disk->paths; |
| disk->paths = path; |
| /* check whether we need to update disk info */ |
| - if (bl_update_path(path, path->state, disk)) { |
| + if (bl_update_path(path->state, disk)) { |
| disk->dev = dev; |
| disk->size = size; |
| disk->valid_path = path; |
| diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c |
| index eabc70c..c5bf71f 100644 |
| --- a/utils/blkmapd/device-inq.c |
| +++ b/utils/blkmapd/device-inq.c |
| @@ -179,6 +179,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename) |
| char *buffer; |
| struct bl_dev_id *dev_root, *dev_id; |
| unsigned int pos, len, current_id = 0; |
| + size_t devid_len = sizeof(struct bl_dev_id) - sizeof(unsigned char); |
| |
| status = bldev_inquire_pages(fd, 0x83, &buffer); |
| if (status) |
| @@ -189,7 +190,11 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename) |
| pos = 0; |
| current_id = 0; |
| len = dev_root->len; |
| - while (pos < (len - sizeof(struct bl_dev_id) + sizeof(unsigned char))) { |
| + |
| + if (len < devid_len) |
| + goto out; |
| + |
| + while (pos < (len - devid_len)) { |
| dev_id = (struct bl_dev_id *)&(dev_root->data[pos]); |
| if ((dev_id->ids & 0xf) < current_id) |
| continue; |
| @@ -221,8 +226,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename) |
| } |
| if (current_id == 3) |
| break; |
| - pos += (dev_id->len + sizeof(struct bl_dev_id) - |
| - sizeof(unsigned char)); |
| + pos += (dev_id->len + devid_len); |
| } |
| out: |
| if (!serial_out) |
| diff --git a/utils/blkmapd/device-process.c b/utils/blkmapd/device-process.c |
| index 5fe3dff..f53a616 100644 |
| --- a/utils/blkmapd/device-process.c |
| +++ b/utils/blkmapd/device-process.c |
| @@ -181,6 +181,8 @@ static int map_sig_to_device(struct bl_sig *sig, struct bl_volume *vol) |
| /* FIXME: should we use better algorithm for disk scan? */ |
| mapped = verify_sig(disk, sig); |
| if (mapped) { |
| + BL_LOG_INFO("%s: using device %s\n", |
| + __func__, disk->valid_path->full_path); |
| vol->param.bv_dev = disk->dev; |
| vol->bv_size = disk->size; |
| break; |
| diff --git a/utils/blkmapd/dm-device.c b/utils/blkmapd/dm-device.c |
| index 0f4f148..24ffcbf 100644 |
| --- a/utils/blkmapd/dm-device.c |
| +++ b/utils/blkmapd/dm-device.c |
| @@ -400,6 +400,8 @@ uint64_t dm_device_create(struct bl_volume *vols, int num_vols) |
| } |
| dev = node->bv_vols[0]->param.bv_dev; |
| tmp = table->params; |
| + BL_LOG_INFO("%s: major %lu minor %lu", __func__, |
| + MAJOR(dev), MINOR(dev)); |
| if (!dm_format_dev(tmp, DM_PARAMS_LEN, |
| MAJOR(dev), MINOR(dev))) { |
| free(table); |
| @@ -459,6 +461,8 @@ uint64_t dm_device_create(struct bl_volume *vols, int num_vols) |
| strcpy(table->target_type, "linear"); |
| tmp = table->params; |
| dev = node->bv_vols[i]->param.bv_dev; |
| + BL_LOG_INFO("%s: major %lu minor %lu", __func__, |
| + MAJOR(dev), MINOR(dev)); |
| if (!dm_format_dev(tmp, DM_PARAMS_LEN, |
| MAJOR(dev), MINOR(dev))) { |
| free(table); |
| diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c |
| index 8391615..53e86ec 100644 |
| --- a/utils/exportfs/exportfs.c |
| +++ b/utils/exportfs/exportfs.c |
| @@ -815,6 +815,8 @@ dump(int verbose, int export_format) |
| c = dumpopt(c, "insecure_locks"); |
| if (ep->e_flags & NFSEXP_NOACL) |
| c = dumpopt(c, "no_acl"); |
| + if (ep->e_flags & NFSEXP_PNFS) |
| + c = dumpopt(c, "pnfs"); |
| if (ep->e_flags & NFSEXP_FSID) |
| c = dumpopt(c, "fsid=%d", ep->e_fsid); |
| if (ep->e_uuid) |
| diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man |
| index 3d974d9..59358e6 100644 |
| --- a/utils/exportfs/exports.man |
| +++ b/utils/exportfs/exports.man |
| @@ -378,6 +378,15 @@ If the client asks for alternative locations for the export point, it |
| will be given this list of alternatives. (Note that actual replication |
| of the filesystem must be handled elsewhere.) |
| |
| +.TP |
| +.IR pnfs |
| +This option allows enables the use of pNFS extension if protocol level |
| +is NFSv4.1 or higher, and the filesystem supports pNFS exports. With |
| +pNFS clients can bypass the server and perform I/O directly to storage |
| +devices. The default can be explicitly requested with the |
| +.I no_pnfs |
| +option. |
| + |
| .SS User ID Mapping |
| .PP |
| .B nfsd |