]> nv-tegra.nvidia Code Review - linux-4.9.git/commitdiff
cifs: add sysfs support to deliver uevent to userspace
authorJean Huang <jeanh@nvidia.com>
Tue, 20 Mar 2018 05:22:32 +0000 (22:22 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Sat, 27 Oct 2018 10:16:26 +0000 (03:16 -0700)
We need more detailed SMB status in userspace to help
users to be aware of NAS status, including failure.

Bug 200396506

Change-Id: I50e1a2c7a4b83b6b3ad006f4f6b34c4080f28fb6
Signed-off-by: Jean Huang <jeanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1679077
(cherry picked from commit dcd8b224377915bcc3112c9704f43965e283518b)
Reviewed-on: https://git-master.nvidia.com/r/1850588
(cherry picked from commit 256fe4883b246c27c7f62dfbaf211aeee49c27db)
Reviewed-on: https://git-master.nvidia.com/r/1934987
GVS: Gerrit_Virtual_Submit
Reviewed-by: Shawn Heo <sheo@nvidia.com>
Tested-by: Shawn Heo <sheo@nvidia.com>
Reviewed-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
fs/cifs/Kconfig
fs/cifs/Makefile
fs/cifs/cifsfs.c
fs/cifs/connect.c
fs/cifs/sysfs.c [new file with mode: 0644]
fs/cifs/sysfs.h [new file with mode: 0644]

index e7b478b4998532231278ca1c07be4481c1951576..7cfd72ec5e258579ea90256dd9cb1de1175517d4 100644 (file)
@@ -209,3 +209,9 @@ config CIFS_FSCACHE
            to be cached locally on disk through the general filesystem cache
            manager. If unsure, say N.
 
+config CIFS_SYSFS
+       bool "sysfs file system support"
+       depends on CIFS && SYSFS
+       help
+         Say Y to export kernel object attributes, controls, and deliver
+          events to userspace
index eed7eb09f46f39294c817c1bca6fa94693f8611c..8a79c63babdf9d14639dea4637940291e337a262 100644 (file)
@@ -19,3 +19,5 @@ cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
 
 cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o \
                            smb2misc.o smb2pdu.o smb2inode.o smb2file.o
+
+cifs-$(CONFIG_CIFS_SYSFS) += sysfs.o
index 87658f63b3743014333434df09192d9e43bb4645..985389f1654ed513438f998cb64b8ee2d910907e 100644 (file)
@@ -53,6 +53,9 @@
 #ifdef CONFIG_CIFS_SMB2
 #include "smb2pdu.h"
 #endif
+#ifdef CONFIG_CIFS_SYSFS
+#include "sysfs.h"
+#endif
 
 int cifsFYI = 0;
 bool traceSMB;
@@ -1322,9 +1325,14 @@ init_cifs(void)
        rc = register_filesystem(&cifs_fs_type);
        if (rc)
                goto out_init_cifs_idmap;
-
+#ifdef CONFIG_CIFS_SYSFS
+        rc = cifs_sysfs_init();
+        if (rc)
+               printk(KERN_WARNING "CIFS: Failed to init sysfs: %d\n", rc);
+#endif
        return 0;
 
+
 out_init_cifs_idmap:
 #ifdef CONFIG_CIFS_ACL
        exit_cifs_idmap();
@@ -1354,6 +1362,9 @@ static void __exit
 exit_cifs(void)
 {
        cifs_dbg(NOISY, "exit_cifs\n");
+#ifdef CONFIG_CIFS_SYSFS
+       cifs_sysfs_exit();
+#endif
        unregister_filesystem(&cifs_fs_type);
        cifs_dfs_release_automount_timer();
 #ifdef CONFIG_CIFS_ACL
index 441d434a48c1c068187019798220e9f224f4365e..14fa88b34ba1d68b44197f4ff31c2ecf3bb8c382 100644 (file)
 #include "smb2proto.h"
 #endif
 
+#ifdef CONFIG_CIFS_SYSFS
+#include "sysfs.h"
+#endif
+
 #define CIFS_PORT 445
 #define RFC1001_PORT 139
 
@@ -339,6 +343,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
 #endif
 
        cifs_dbg(FYI, "Reconnecting tcp session\n");
+#ifdef CONFIG_CIFS_SYSFS
+       cifs_sysfs_notify_change(server->hostname, RECONNECTING);
+#endif
 
        /* before reconnecting the tcp session, mark the smb session (uid)
                and the tid bad so they are not used until reconnected */
@@ -406,6 +413,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
                        mutex_unlock(&server->srv_mutex);
                        msleep(3000);
                } else {
+#ifdef CONFIG_CIFS_SYSFS
+                       cifs_sysfs_notify_change(server->hostname, RECONNECTED);
+#endif
                        atomic_inc(&tcpSesReconnectCount);
                        spin_lock(&GlobalMid_Lock);
                        if (server->tcpStatus != CifsExiting)
@@ -2661,6 +2671,9 @@ cifs_put_tcon(struct cifs_tcon *tcon)
                ses->server->ops->tree_disconnect(xid, tcon);
        _free_xid(xid);
 
+#ifdef CONFIG_CIFS_SYSFS
+       cifs_sysfs_notify_change(tcon->treeName, DISCONNECTED);
+#endif
        cifs_fscache_release_super_cookie(tcon);
        tconInfoFree(tcon);
        cifs_put_smb_ses(ses);
@@ -2714,6 +2727,10 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
        if (rc)
                goto out_fail;
 
+#ifdef CONFIG_CIFS_SYSFS
+       cifs_sysfs_notify_change(tcon->treeName, CONNECTED);
+#endif
+
        if (volume_info->nodfs) {
                tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
                cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
diff --git a/fs/cifs/sysfs.c b/fs/cifs/sysfs.c
new file mode 100644 (file)
index 0000000..06306bc
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * sysfs for cifs
+ *
+ * Copyright (c) 2018, NVIDIA Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kobject.h>
+#include <linux/slab.h>
+#include "cifsglob.h"
+#include "sysfs.h"
+
+static struct kset *cifs_sysfs_kset;
+static struct kobject *cifs_sysfs_kobj;
+
+static struct kobj_type cifs_uevent_ktype = {
+
+};
+
+void cifs_sysfs_notify_change(const char* source, cifs_event_type event_type) {
+       char env_source[30];
+       char env_state[30];
+       char *envp[3] = { env_source, env_state, NULL };
+       sprintf(env_source, "SOURCE=%s", source);
+       sprintf(env_state, "STATE=%d", event_type);
+       kobject_uevent_env(cifs_sysfs_kobj, KOBJ_CHANGE, envp);
+}
+
+int cifs_sysfs_init(void) {
+       int ret;
+       cifs_sysfs_kset = kset_create_and_add("cifs", NULL, fs_kobj);
+       if (!cifs_sysfs_kset) {
+               return -ENOMEM;
+       }
+       cifs_sysfs_kobj = kzalloc(sizeof(*cifs_sysfs_kobj),
+               GFP_KERNEL);
+       if (!cifs_sysfs_kobj) {
+               return -ENOMEM;
+       }
+       cifs_sysfs_kobj->kset = cifs_sysfs_kset;
+       ret = kobject_init_and_add(cifs_sysfs_kobj, &cifs_uevent_ktype, NULL, "uevent");
+       if (!ret) {
+               kobject_uevent(cifs_sysfs_kobj, KOBJ_ADD);
+       } else {
+               kfree(cifs_sysfs_kobj);
+       }
+       return ret;
+}
+
+void cifs_sysfs_exit(void) {
+       kobject_uevent(cifs_sysfs_kobj, KOBJ_REMOVE);
+       kobject_put(cifs_sysfs_kobj);
+       kset_unregister(cifs_sysfs_kset);
+}
diff --git a/fs/cifs/sysfs.h b/fs/cifs/sysfs.h
new file mode 100644 (file)
index 0000000..538e0a5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * sysfs header for cifs
+ *
+ * Copyright (c) 2018, NVIDIA Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _CIFS_SYSFS_H
+#define _CIFS_SYSFS_H
+
+typedef enum {
+       CONNECTED = 1,
+       DISCONNECTED,
+       RECONNECTING,
+       RECONNECTED,
+} cifs_event_type;
+
+void cifs_sysfs_notify_change(const char* source, cifs_event_type type);
+int cifs_sysfs_init(void);
+void cifs_sysfs_exit(void);
+#endif