ksmbd: request update to stale share config
authorAtte Heikkilä <atteh.mailbox@gmail.com>
Mon, 8 Aug 2022 22:02:14 +0000 (01:02 +0300)
committerSteve French <stfrench@microsoft.com>
Thu, 11 Aug 2022 06:05:18 +0000 (01:05 -0500)
ksmbd_share_config_get() retrieves the cached share config as long
as there is at least one connection to the share. This is an issue when
the user space utilities are used to update share configs. In that case
there is a need to inform ksmbd that it should not use the cached share
config for a new connection to the share. With these changes the tree
connection flag KSMBD_TREE_CONN_FLAG_UPDATE indicates this. When this
flag is set, ksmbd removes the share config from the shares hash table
meaning that ksmbd_share_config_get() ends up requesting a share config
from user space.

Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/ksmbd/ksmbd_netlink.h
fs/ksmbd/mgmt/share_config.c
fs/ksmbd/mgmt/share_config.h
fs/ksmbd/mgmt/tree_connect.c
fs/ksmbd/smb2pdu.c

index 52aa0adeb95198f56142e46ebebd98ddce401f67..e0cbcfa98c7ebb64e506404d9c476afcdede782f 100644 (file)
@@ -349,6 +349,7 @@ enum KSMBD_TREE_CONN_STATUS {
 #define KSMBD_SHARE_FLAG_STREAMS               BIT(11)
 #define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS       BIT(12)
 #define KSMBD_SHARE_FLAG_ACL_XATTR             BIT(13)
+#define KSMBD_SHARE_FLAG_UPDATE                BIT(14)
 
 /*
  * Tree connect request flags.
@@ -364,6 +365,7 @@ enum KSMBD_TREE_CONN_STATUS {
 #define KSMBD_TREE_CONN_FLAG_READ_ONLY         BIT(1)
 #define KSMBD_TREE_CONN_FLAG_WRITABLE          BIT(2)
 #define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT     BIT(3)
+#define KSMBD_TREE_CONN_FLAG_UPDATE            BIT(4)
 
 /*
  * RPC over IPC.
index 70655af93b440b7711f3757c6b9d464c54f28f97..c9bca1c2c83490ebcd1b51de7b96f1126c46b23a 100644 (file)
@@ -51,12 +51,16 @@ static void kill_share(struct ksmbd_share_config *share)
        kfree(share);
 }
 
-void __ksmbd_share_config_put(struct ksmbd_share_config *share)
+void ksmbd_share_config_del(struct ksmbd_share_config *share)
 {
        down_write(&shares_table_lock);
        hash_del(&share->hlist);
        up_write(&shares_table_lock);
+}
 
+void __ksmbd_share_config_put(struct ksmbd_share_config *share)
+{
+       ksmbd_share_config_del(share);
        kill_share(share);
 }
 
index 28bf3511763f4bac6ebecf21ad746a65431fa616..902f2cb1963a93b9f442341afd7a7d453fd81efc 100644 (file)
@@ -64,6 +64,7 @@ static inline int test_share_config_flag(struct ksmbd_share_config *share,
        return share->flags & flag;
 }
 
+void ksmbd_share_config_del(struct ksmbd_share_config *share);
 void __ksmbd_share_config_put(struct ksmbd_share_config *share);
 
 static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
index dd262daa2c4a5af0c54739dd520c2909a0b3847d..97ab7987df6ebfa8b004b924513f560bedaaae6a 100644 (file)
@@ -57,6 +57,20 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
                goto out_error;
 
        tree_conn->flags = resp->connection_flags;
+       if (test_tree_conn_flag(tree_conn, KSMBD_TREE_CONN_FLAG_UPDATE)) {
+               struct ksmbd_share_config *new_sc;
+
+               ksmbd_share_config_del(sc);
+               new_sc = ksmbd_share_config_get(share_name);
+               if (!new_sc) {
+                       pr_err("Failed to update stale share config\n");
+                       status.ret = -ESTALE;
+                       goto out_error;
+               }
+               ksmbd_share_config_put(sc);
+               sc = new_sc;
+       }
+
        tree_conn->user = sess->user;
        tree_conn->share_conf = sc;
        status.tree_conn = tree_conn;
index 1f9a2cda0c58fd8992c653657ea7abf7e237f7e9..b5c36657ecfdd31549d4bde83c0d917c7acf4268 100644 (file)
@@ -1944,6 +1944,7 @@ out_err1:
                rsp->hdr.Status = STATUS_SUCCESS;
                rc = 0;
                break;
+       case -ESTALE:
        case -ENOENT:
        case KSMBD_TREE_CONN_STATUS_NO_SHARE:
                rsp->hdr.Status = STATUS_BAD_NETWORK_NAME;