[SSI] openssi/nfs-utils/utils/statd Makefile, 1.1.15.1, 1.1.15.1.4.1 monitor.c, 1.1.15.1, 1.1.15.1.4.1 notify.c, 1.1.15.1, 1.1.15.1.4.1 notlist.h, 1.1.15.1, 1.1.15.1.4.1 rmtcall.c, 1.1.15.2, 1.1.15.2.2.1 statd.c, 1.1.15.1, 1.1.15.1.4.1 statd.h, 1.1.15.1, 1.1.15.1.4.1 state.c, 1.1.15.1, 1.1.15.1.4.1
Roger Tsang <[email protected]> Thu, 15 Jul 2010 03:47:19 +0000
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv13321/utils/statd
Modified Files:
Tag: OPENSSI-CENTOS
Makefile monitor.c notify.c notlist.h rmtcall.c statd.c
statd.h state.c
Log Message:
OpenSSI changes for nfs-utils-1.0.6-93.EL4 CentOS 4
Index: statd.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/statd.c,v
retrieving revision 1.1.15.1
retrieving revision 1.1.15.1.4.1
diff -u -d -r1.1.15.1 -r1.1.15.1.4.1
--- statd.c 4 Jul 2010 22:21:51 -0000 1.1.15.1
+++ statd.c 15 Jul 2010 03:47:17 -0000 1.1.15.1.4.1
@@ -28,6 +28,10 @@
#include <sys/types.h>
#include <sys/socket.h>
+/* This should be the high-order bit for whatever size u_long is */
+#include <limits.h>
+#define CVIP_PROG_BIT (LONG_MIN)
+
/* Added to enable specification of state directory path at run-time
* [email protected]
*/
@@ -109,6 +113,23 @@
exit (0);
}
+int port = 0, out_port = 0;
+
+static void
+convert_to_cvip(int sig)
+{
+ /* Don't convert if we are already in do_cvip mode */
+ if (do_cvip)
+ return;
+ do_cvip = TRUE;
+ pmap_unset (SM_PROG|CVIP_PROG_BIT, SM_VERS);
+ cvip_change_state ();
+ cvip_shuffle_dirs (); /* Move directory names around */
+ cvip_notify_hosts (); /* Send out notify requests */
+ /* Try to re-do this and see if it works */
+ rpc_init_addr("statd", SM_PROG, SM_VERS, sm_prog_1, port, INADDR_ANY, SSI_PMAP_REGULAR|SSI_PMAP_CVIP);
+}
+
static void
sigusr (int sig)
{
@@ -163,6 +184,7 @@
fprintf(stderr," -P State directory path.\n");
fprintf(stderr," -N Run in notify only mode.\n");
fprintf(stderr," -H Specify a high-availability callout program.\n");
+ fprintf(stderr," -C Operate cluster NFS server\n");
}
static const char *pidfile = "/var/run/rpc.statd.pid";
@@ -252,9 +274,15 @@
/* Set hostname */
MY_NAME = NULL;
+ CVIP_MY_NAME = NULL;
+
+ /*
+ * See if we are running on an SSI kernel
+ */
+ ssi = cluster_ssiconfig();
/* Process command line switches */
- while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:", longopts, NULL)) != EOF) {
+ while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:C", longopts, NULL)) != EOF) {
switch (arg) {
case 'V': /* Version */
case 'v':
@@ -321,6 +349,9 @@
sprintf(SM_STAT_PATH, "%s/state", DIR_BASE );
}
break;
+ case 'C':
+ do_cvip = TRUE;
+ break;
case 'H': /* PRC: specify the ha-callout program */
if ((ha_callout_prog = xstrdup(optarg)) == NULL) {
fprintf(stderr, "%s: xstrdup(%s) failed!\n",
@@ -431,19 +462,23 @@
/* Child. */
+
log_init (name_p,version_p);
log_modes();
+ if (ssi)
+ signal (SIGHUP, convert_to_cvip);
+ else
+ signal (SIGHUP, killer);
+
sa.sa_handler = killer;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGINT);
sigaddset(&sa.sa_mask, SIGTERM);
- sigaddset(&sa.sa_mask, SIGHUP);
sa.sa_flags = 0;
(void) sigaction(SIGINT, &sa, NULL);
(void) sigaction(SIGTERM, &sa, NULL);
- (void) sigaction(SIGHUP, &sa, NULL);
/* PRC: trap SIGUSR1 to re-read notify list from disk */
signal(SIGUSR1, sigusr);
@@ -469,9 +504,21 @@
* Juan C. Gomez [email protected]
*/
pmap_unset (SM_PROG, SM_VERS);
+ if (ssi)
+ pmap_unset (SM_PROG|CVIP_PROG_BIT, SM_VERS);
/* this registers both UDP and TCP services */
+ /* future: IP aliasing
rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port);
+ */
+
+ /* this registers both UDP and TCP services */
+ if (ssi && do_cvip)
+ rpc_init_addr("statd", SM_PROG, SM_VERS,
+ sm_prog_1, port, INADDR_ANY,
+ SSI_PMAP_REGULAR|SSI_PMAP_CVIP);
+ else
+ rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port);
}
if (doonce++ < 1)
@@ -489,6 +536,13 @@
}
notify_hosts (); /* Send out notify requests */
+ if (ssi) {
+ if(do_cvip){
+ cvip_change_state ();
+ cvip_shuffle_dirs (); /* Move directory names around */
+ cvip_notify_hosts (); /* Send out notify requests */
+ }
+ }
++restart;
/*
Index: state.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/state.c,v
retrieving revision 1.1.15.1
retrieving revision 1.1.15.1.4.1
diff -u -d -r1.1.15.1 -r1.1.15.1.4.1
--- state.c 4 Jul 2010 22:21:51 -0000 1.1.15.1
+++ state.c 15 Jul 2010 03:47:17 -0000 1.1.15.1.4.1
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include "statd.h"
+#include "xlog.h"
/*
@@ -60,8 +61,13 @@
char fullhost[SM_MAXSTRLEN + 1];
struct hostent *hostinfo;
+ if (ssi) {
+ if (cluster_get_nodename (fullhost, SM_MAXSTRLEN) == -1)
+ die ("cluster_get_nodename: %s", strerror (errno));
+ } else {
if (gethostname (fullhost, SM_MAXSTRLEN) == -1)
die ("gethostname: %s", strerror (errno));
+ }
if ((hostinfo = gethostbyname (fullhost)) == NULL)
note (N_ERROR, "gethostbyname error for %s", fullhost);
@@ -76,6 +82,63 @@
/*
+ * Most NSM's keep the status number in an ASCII file. I'm keeping it
+ * as an int (4-byte binary) for now...
+ */
+void
+cvip_change_state (void)
+{
+ int fd, size;
+ extern short int restart;
+
+ if ((fd = open (CVIP_SM_STAT_PATH, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) == -1)
+ die ("open (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+
+ if ((size = read (fd, &CVIP_MY_STATE, sizeof CVIP_MY_STATE)) == -1)
+ die ("read (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+
+ if (size != 0 && size != sizeof CVIP_MY_STATE) {
+ xlog (L_ERROR, "Error in status file format...correcting.");
+
+ if (close (fd) == -1)
+ die ("close (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+
+ if ((fd = creat (CVIP_SM_STAT_PATH, S_IRUSR | S_IWUSR)) == -1)
+ die ("creat (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+ }
+ xlog (N_DEBUG, "New CVIP state: %u", (++CVIP_MY_STATE % 2) ? CVIP_MY_STATE : ++CVIP_MY_STATE);
+
+ if (lseek (fd, 0, SEEK_SET) == -1)
+ die ("lseek (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+
+ if (write (fd, &CVIP_MY_STATE, sizeof CVIP_MY_STATE) != sizeof CVIP_MY_STATE)
+ die ("write (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+
+ if (fsync (fd) == -1)
+ xlog (L_ERROR, "fsync (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+
+ if (close (fd) == -1)
+ xlog (L_ERROR, "close (%s): %s", CVIP_SM_STAT_PATH, strerror (errno));
+
+ if (CVIP_MY_NAME == NULL) {
+ char fullhost[SM_MAXSTRLEN + 1];
+ struct hostent *hostinfo;
+
+ if (cluster_get_clustername (fullhost, SM_MAXSTRLEN) == -1)
+ die ("cluster_get_clustername: %s", strerror (errno));
+
+ if ((hostinfo = gethostbyname (fullhost)) == NULL)
+ xlog (L_ERROR, "gethostbyname error for %s", fullhost);
+ else {
+ strncpy (fullhost, hostinfo->h_name, sizeof (fullhost) - 1);
+ fullhost[sizeof (fullhost) - 1] = '\0';
+ }
+
+ CVIP_MY_NAME = xstrdup (fullhost);
+ }
+}
+
+/*
* Fairly traditional use of two directories for this.
*/
void
@@ -86,6 +149,8 @@
struct stat st;
char *src, *dst;
int len1, len2, len;
+
+ memset (&st, 0, sizeof st);
if (stat (SM_DIR, &st) == -1 && errno != ENOENT)
die ("stat (%s): %s", SM_DIR, strerror (errno));
@@ -124,3 +189,55 @@
if (closedir (nld) == -1)
note (N_ERROR, "closedir (%s): %s", SM_DIR, strerror (errno));
}
+
+/*
+ * Fairly traditional use of two directories for this.
+ */
+void
+cvip_shuffle_dirs (void)
+{
+ DIR *nld;
+ struct dirent *de;
+ struct stat st;
+ char *src, *dst;
+ int len1, len2, len;
+
+ memset (&st, 0, sizeof st);
+
+ if (stat (CVIP_SM_DIR, &st) == -1 && errno != ENOENT)
+ die ("stat (%s): %s", CVIP_SM_DIR, strerror (errno));
+
+ if (!S_ISDIR (st.st_mode))
+ if (mkdir (CVIP_SM_DIR, S_IRWXU) == -1)
+ die ("mkdir (%s): %s", CVIP_SM_DIR, strerror (errno));
+
+ memset (&st, 0, sizeof st);
+
+ if (stat (CVIP_SM_BAK_DIR, &st) == -1 && errno != ENOENT)
+ die ("stat (%s): %s", CVIP_SM_BAK_DIR, strerror (errno));
+
+ if (!S_ISDIR (st.st_mode))
+ if (mkdir (CVIP_SM_BAK_DIR, S_IRWXU) == -1)
+ die ("mkdir (%s): %s", SM_BAK_DIR, strerror (errno));
+
+ if (!(nld = opendir (CVIP_SM_DIR)))
+ die ("opendir (%s): %s", CVIP_SM_DIR, strerror (errno));
+
+ len1=strlen(CVIP_SM_DIR);
+ len2=strlen(CVIP_SM_BAK_DIR);
+ while ((de = readdir (nld))) {
+ if (de->d_name[0] == '.')
+ continue;
+ len=strlen(de->d_name);
+ src=xmalloc(len1+len+2);
+ dst=xmalloc(len2+len+2);
+ sprintf (src, "%s/%s", CVIP_SM_DIR, de->d_name);
+ sprintf (dst, "%s/%s", CVIP_SM_BAK_DIR, de->d_name);
+ if (rename (src, dst) == -1)
+ die ("rename (%s to %s): %s", CVIP_SM_DIR, CVIP_SM_BAK_DIR, strerror (errno));
+ free(src);
+ free(dst);
+ }
+ if (closedir (nld) == -1)
+ xlog (L_ERROR, "closedir (%s): %s", CVIP_SM_DIR, strerror (errno));
+}
Index: notlist.h
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/notlist.h,v
retrieving revision 1.1.15.1
retrieving revision 1.1.15.1.4.1
diff -u -d -r1.1.15.1 -r1.1.15.1.4.1
--- notlist.h 4 Jul 2010 22:21:51 -0000 1.1.15.1
+++ notlist.h 15 Jul 2010 03:47:17 -0000 1.1.15.1.4.1
@@ -27,6 +27,7 @@
#define NOTIFY_REBOOT 0 /* notify remote of our reboot */
#define NOTIFY_CALLBACK 1 /* notify client of remote reboot */
+#define CVIP_NOTIFY_REBOOT 2 /* notify client of cvip reboot */
/*
* Global Variables
Index: rmtcall.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/rmtcall.c,v
retrieving revision 1.1.15.2
retrieving revision 1.1.15.2.2.1
diff -u -d -r1.1.15.2 -r1.1.15.2.2.1
--- rmtcall.c 15 Jul 2010 03:38:31 -0000 1.1.15.2
+++ rmtcall.c 15 Jul 2010 03:47:17 -0000 1.1.15.2.2.1
@@ -139,7 +139,7 @@
{
char *hname;
- if (NL_TYPE(lp) == NOTIFY_REBOOT)
+ if (NL_TYPE(lp) == NOTIFY_REBOOT || NL_TYPE(lp) == CVIP_NOTIFY_REBOOT)
hname = NL_MON_NAME(lp);
else
hname = NL_MY_NAME(lp);
@@ -162,7 +162,7 @@
struct hostent *hp;
char *hname;
- if (NL_TYPE(lp) == NOTIFY_REBOOT)
+ if (NL_TYPE(lp) == NOTIFY_REBOOT || NL_TYPE(lp) == CVIP_NOTIFY_REBOOT)
hname = NL_MON_NAME(lp);
else
hname = NL_MY_NAME(lp);
@@ -377,6 +377,17 @@
objp = &new_stat;
break;
+ case CVIP_NOTIFY_REBOOT:
+ prog = SM_PROG;
+ vers = SM_VERS;
+ proc = SM_NOTIFY;
+
+ /* Use source address for notify replies */
+ sin.sin_addr = lp->addr;
+
+ func = (xdrproc_t) xdr_stat_chge;
+ objp = &SM_cvip_stat_chge;
+ break;
case NOTIFY_CALLBACK:
prog = NL_MY_PROG(lp);
vers = NL_MY_VERS(lp);
@@ -435,11 +446,15 @@
}
note(N_WARNING, "recv_rply: [%s] service %d not registered",
inet_ntoa(lp->addr),
- NL_TYPE(lp) == NOTIFY_REBOOT? SM_PROG : NL_MY_PROG(lp));
+ (NL_TYPE(lp) == NOTIFY_REBOOT|| NL_TYPE(lp) == CVIP_NOTIFY_REBOOT)? SM_PROG : NL_MY_PROG(lp));
} else if (NL_TYPE(lp) == NOTIFY_REBOOT) {
dprintf(N_DEBUG, "Notification of %s succeeded.",
NL_MON_NAME(lp));
xunlink(SM_BAK_DIR, NL_MON_NAME(lp), 0);
+ } else if (NL_TYPE(lp) == CVIP_NOTIFY_REBOOT) {
+ dprintf(N_DEBUG, "CVIP Notification of %s succeeded.",
+ NL_MON_NAME(lp));
+ xunlink(CVIP_SM_BAK_DIR, NL_MON_NAME(lp), 0);
} else {
dprintf(N_DEBUG, "Callback to %s (for %d) succeeded.",
NL_MY_NAME(lp), NL_MON_NAME(lp));
@@ -482,6 +497,9 @@
/* PRC: do the HA callout */
ha_callout("del-client", NL_MON_NAME(entry), NL_MY_NAME(entry), -1);
xunlink(SM_BAK_DIR, NL_MON_NAME(entry), 0);
+ // Do we want to do this ???
+ if (ssi)
+ xunlink(CVIP_SM_BAK_DIR, NL_MON_NAME(entry), 0);
nlist_free(¬ify, entry);
}
}
Index: statd.h
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/statd.h,v
retrieving revision 1.1.15.1
retrieving revision 1.1.15.1.4.1
diff -u -d -r1.1.15.1 -r1.1.15.1.4.1
--- statd.h 4 Jul 2010 22:21:51 -0000 1.1.15.1
+++ statd.h 15 Jul 2010 03:47:17 -0000 1.1.15.1.4.1
@@ -20,10 +20,25 @@
# define DEFAULT_DIR_BASE "/var/lib/nfs/" STATD_PATH_XTN
#endif
+#define CVIP_STATD_PATH_XTN "statd.cvip/"
+
+#if defined(NFS_STATEDIR)
+# define CVIP_DIR_BASE NFS_STATEDIR "/" CVIP_STATD_PATH_XTN
+#else
+# define CVIP_DIR_BASE "/var/lib/nfs/" CVIP_STATD_PATH_XTN
+#endif
+
+
#define DEFAULT_SM_DIR DEFAULT_DIR_BASE "sm"
#define DEFAULT_SM_BAK_DIR DEFAULT_DIR_BASE "sm.bak"
#define DEFAULT_SM_STAT_PATH DEFAULT_DIR_BASE "state"
+#define CVIP_SM_DIR CVIP_DIR_BASE "sm"
+#define CVIP_SM_BAK_DIR CVIP_DIR_BASE "sm.bak"
+#define CVIP_SM_STAT_PATH CVIP_DIR_BASE "state"
+
+int ssi;
+
/* Added to support run-time specification of state directory path.
* [email protected]
*/
@@ -60,6 +75,14 @@
#define MY_NAME SM_stat_chge.mon_name
#define MY_STATE SM_stat_chge.state
+int do_cvip;
+extern void cvip_change_state(void);
+extern void cvip_notify_hosts(void);
+extern void cvip_shuffle_dirs(void);
+stat_chge SM_cvip_stat_chge;
+#define CVIP_MY_NAME SM_cvip_stat_chge.mon_name
+#define CVIP_MY_STATE SM_cvip_stat_chge.state
+
/*
* Some timeout values. (Timeout values are in whole seconds.)
*/
Index: Makefile
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/Makefile,v
retrieving revision 1.1.15.1
retrieving revision 1.1.15.1.4.1
diff -u -d -r1.1.15.1 -r1.1.15.1.4.1
--- Makefile 4 Jul 2010 22:21:51 -0000 1.1.15.1
+++ Makefile 15 Jul 2010 03:47:17 -0000 1.1.15.1.4.1
@@ -16,7 +16,7 @@
PREFIX = rpc.
OBJS = $(SRCS:.c=.o)
CCOPTS = $(DEBUG) $(SIMUL)
-LIBS = -lexport -lnfs -lmisc $(LIBWRAP) $(LIBNSL)
+LIBS = -lexport -lnfs -lmisc $(LIBWRAP) $(LIBNSL) -lcluster
SRCS = $(RPCSRCS) $(SIMSRCS) \
callback.c notlist.c log.c misc.c monitor.c notify.c simu.c \
Index: notify.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/notify.c,v
retrieving revision 1.1.15.1
retrieving revision 1.1.15.1.4.1
diff -u -d -r1.1.15.1 -r1.1.15.1.4.1
--- notify.c 4 Jul 2010 22:21:51 -0000 1.1.15.1
+++ notify.c 15 Jul 2010 03:47:17 -0000 1.1.15.1.4.1
@@ -20,6 +20,7 @@
#include "misc.h"
#include "statd.h"
#include "notlist.h"
+#include "xlog.h"
/*
* Initial (startup) notify list.
@@ -73,3 +74,50 @@
exit(1);
}
}
+
+/*
+ * Get list of hosts from stable storage, build list of hosts to
+ * contact. These hosts are added to the global RPC notify list
+ * which is processed as soon as statd enters svc_run.
+ */
+void
+cvip_notify_hosts(void)
+{
+ DIR *nld;
+ struct dirent *de;
+ notify_list *call;
+
+ if (!(nld = opendir(CVIP_SM_BAK_DIR))) {
+ perror("opendir");
+ exit(errno);
+ }
+
+ while ((de = readdir(nld))) {
+ if (de->d_name[0] == '.')
+ continue;
+
+ /* The following can happen for loopback NFS mounts
+ * (e.g. with cfsd) */
+ if (matchhostname(de->d_name, CVIP_MY_NAME)
+ || matchhostname(de->d_name, "localhost")) {
+ char *fname;
+ fname=xmalloc(strlen(CVIP_SM_BAK_DIR)+sizeof(de->d_name)+2);
+ dprintf(N_DEBUG, "We're on our own notify list?!?");
+ sprintf(fname, CVIP_SM_BAK_DIR "/%s", de->d_name);
+ if (unlink(fname))
+ xlog(L_ERROR, "unlink(%s): %s",
+ fname, strerror(errno));
+ free(fname);
+ continue;
+ }
+
+ call = nlist_new(CVIP_MY_NAME, de->d_name, -1);
+ NL_TYPE(call) = CVIP_NOTIFY_REBOOT;
+ nlist_insert(¬ify, call);
+ }
+
+ if (closedir(nld) == -1) {
+ perror("closedir");
+ exit(1);
+ }
+}
Index: monitor.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/nfs-utils/utils/statd/Attic/monitor.c,v
retrieving revision 1.1.15.1
retrieving revision 1.1.15.1.4.1
diff -u -d -r1.1.15.1 -r1.1.15.1.4.1
--- monitor.c 4 Jul 2010 22:21:51 -0000 1.1.15.1
+++ monitor.c 15 Jul 2010 03:47:17 -0000 1.1.15.1.4.1
@@ -22,6 +22,8 @@
#include "notlist.h"
#include "ha-callout.h"
+#include "xlog.h"
+
notify_list * rtnl = NULL; /* Run-time notify list. */
@@ -179,6 +181,20 @@
goto failure;
}
free(path);
+
+ // inserting mon_name in statd.cvip too
+ if (ssi) {
+ path=xmalloc(strlen(CVIP_SM_DIR)+strlen(mon_name)+3);
+ sprintf(path, CVIP_SM_DIR "/%s", mon_name);
+ if ((fd = open(path, O_WRONLY|O_SYNC|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
+ /* Didn't fly. We won't monitor. */
+ xlog(L_ERROR, "creat(%s) failed: %m", path);
+ nlist_free(NULL, clnt);
+ free(path);
+ goto failure;
+ }
+ free(path);
+ }
/* PRC: do the HA callout: */
ha_callout("add-client", mon_name, my_name, -1);
nlist_insert(&rtnl, clnt);
@@ -260,7 +276,8 @@
nlist_free(&rtnl, clnt);
xunlink(SM_DIR, mon_name, 1);
-
+ if (ssi)
+ xunlink(CVIP_SM_DIR, mon_name, 1);
return (&result);
} else
clnt = NL_NEXT(clnt);
@@ -324,6 +341,8 @@
ha_callout("del-client", mon_name, my_name, -1);
nlist_free(&rtnl, clnt);
xunlink(SM_DIR, mon_name, 1);
+ if (ssi)
+ xunlink(CVIP_SM_DIR, mon_name, 1);
++count;
clnt = temp;
} else
------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first