Whamcloud - gitweb
LU-1778 llite: fix inconsistencies of root squash feature 00/5700/19
authorGregoire Pichon <gregoire.pichon@bull.net>
Thu, 13 Feb 2014 15:33:34 +0000 (16:33 +0100)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 9 May 2014 14:55:56 +0000 (14:55 +0000)
Root squash exhibits inconsistent behaviour on a client when
enabled. If a file is not cached on the client, then root will get
a permission denied error when accessing the file. When
the file has recently been accessed by a regular user and is
still in cache, root will be able to access the file without error
because the permission check is only done by the client that
isn't aware of root squash.

While the only real security benefit from root squash is to deny
clients access to files owned by root itself, it also makes sense
to treat file access on the client in a consistent manner
regardless of whether the file is in cache or not.

This patch adds root squash settings to llite so that client is able
to apply root squashing when it is relevant.

Configuration of MDT root squash settings will automatically be
applied to llite config log as well.

Update cfs_str2num_check() routine by removing any modification
of the specified string parameter. Since string can come from ls_str
field of a lstr structure, this avoids inconsistent ls_len field.

Signed-off-by: Gregoire Pichon <gregoire.pichon@bull.net>
Change-Id: Ie52d04424d0937af9fed777a4e4912c90405c19b
Reviewed-on: http://review.whamcloud.com/5700
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
14 files changed:
libcfs/libcfs/libcfs_string.c
lustre/include/lprocfs_status.h
lustre/include/obd_class.h
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/lproc_llite.c
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_lib.c
lustre/mdt/mdt_lproc.c
lustre/mgs/mgs_llog.c
lustre/obdclass/lprocfs_status.c
lustre/tests/conf-sanity.sh

index ae6a9e3..4ef54fa 100644 (file)
@@ -326,7 +326,6 @@ cfs_str2num_check(char *str, int nob, unsigned *num,
 {
        char    *endp;
 
 {
        char    *endp;
 
-       str = cfs_trimwhite(str);
        *num = strtoul(str, &endp, 0);
        if (endp == str)
                return 0;
        *num = strtoul(str, &endp, 0);
        if (endp == str)
                return 0;
index 0d6fd4c..42cec9e 100644 (file)
@@ -975,6 +975,12 @@ ssize_t
 lprocfs_obd_max_pages_per_rpc_seq_write(struct file *file, const char *buffer,
                                       size_t count, loff_t *off);
 
 lprocfs_obd_max_pages_per_rpc_seq_write(struct file *file, const char *buffer,
                                       size_t count, loff_t *off);
 
+struct root_squash_info;
+int lprocfs_wr_root_squash(const char *buffer, unsigned long count,
+                          struct root_squash_info *squash, char *name);
+int lprocfs_wr_nosquash_nids(const char *buffer, unsigned long count,
+                            struct root_squash_info *squash, char *name);
+
 /* all quota proc functions */
 extern int lprocfs_quota_rd_bunit(char *page, char **start,
                                   off_t off, int count,
 /* all quota proc functions */
 extern int lprocfs_quota_rd_bunit(char *page, char **start,
                                   off_t off, int count,
index 8db8904..b5e2ab5 100644 (file)
@@ -2102,6 +2102,15 @@ void class_exit_uuidlist(void);
 /* prng.c */
 #define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t))
 
 /* prng.c */
 #define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t))
 
+/* root squash info */
+struct rw_semaphore;
+struct root_squash_info {
+       uid_t                   rsi_uid;
+       gid_t                   rsi_gid;
+       struct list_head        rsi_nosquash_nids;
+       struct rw_semaphore     rsi_sem;
+};
+
 #ifdef __KERNEL__
 int server_name2index(const char *svname, __u32 *idx, const char **endptr);
 #else
 #ifdef __KERNEL__
 int server_name2index(const char *svname, __u32 *idx, const char **endptr);
 #else
index 99dc465..8b4e3a3 100644 (file)
@@ -45,6 +45,7 @@
 #include <lustre_lite.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
 #include <lustre_lite.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
+#include <linux/sched.h>
 #include "llite_internal.h"
 #include <lustre/ll_fiemap.h>
 #include <lustre_ioctl.h>
 #include "llite_internal.h"
 #include <lustre/ll_fiemap.h>
 #include <lustre_ioctl.h>
@@ -3507,8 +3508,14 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
 # endif
 #endif
 {
 # endif
 #endif
 {
-        int rc = 0;
-        ENTRY;
+       int rc = 0;
+       struct ll_sb_info *sbi;
+       struct root_squash_info *squash;
+       struct cred *cred = NULL;
+       const struct cred *old_cred = NULL;
+       cfs_cap_t cap;
+       bool squash_id = false;
+       ENTRY;
 
 #ifdef MAY_NOT_BLOCK
        if (mask & MAY_NOT_BLOCK)
 
 #ifdef MAY_NOT_BLOCK
        if (mask & MAY_NOT_BLOCK)
@@ -3531,11 +3538,46 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n",
               PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask);
 
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n",
               PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask);
 
-       if (ll_i2sbi(inode)->ll_flags & LL_SBI_RMT_CLIENT)
-               return lustre_check_remote_perm(inode, mask);
+       /* squash fsuid/fsgid if needed */
+       sbi = ll_i2sbi(inode);
+       squash = &sbi->ll_squash;
+       if (unlikely(squash->rsi_uid != 0 &&
+                    current_fsuid() == 0 &&
+                    !(sbi->ll_flags & LL_SBI_NOROOTSQUASH))) {
+                       squash_id = true;
+       }
+       if (squash_id) {
+               CDEBUG(D_OTHER, "squash creds (%d:%d)=>(%d:%d)\n",
+                      current_fsuid(), current_fsgid(),
+                      squash->rsi_uid, squash->rsi_gid);
+
+               /* update current process's credentials
+                * and FS capability */
+               cred = prepare_creds();
+               if (cred == NULL)
+                       RETURN(-ENOMEM);
 
 
-       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_INODE_PERM, 1);
-       rc = ll_generic_permission(inode, mask, flags, ll_check_acl);
+               cred->fsuid = squash->rsi_uid;
+               cred->fsgid = squash->rsi_gid;
+               for (cap = 0; cap < sizeof(cfs_cap_t) * 8; cap++) {
+                       if ((1 << cap) & CFS_CAP_FS_MASK)
+                               cap_lower(cred->cap_effective, cap);
+               }
+               old_cred = override_creds(cred);
+       }
+
+       ll_stats_ops_tally(sbi, LPROC_LL_INODE_PERM, 1);
+
+       if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
+               rc = lustre_check_remote_perm(inode, mask);
+       else
+               rc = ll_generic_permission(inode, mask, flags, ll_check_acl);
+
+       /* restore current process's credentials and FS capability */
+       if (squash_id) {
+               revert_creds(old_cred);
+               put_cred(cred);
+       }
 
        RETURN(rc);
 }
 
        RETURN(rc);
 }
index 71ebd55..edebe5d 100644 (file)
@@ -429,6 +429,7 @@ enum stats_track_type {
 #define LL_SBI_LAYOUT_LOCK    0x20000 /* layout lock support */
 #define LL_SBI_USER_FID2PATH  0x40000 /* allow fid2path by unprivileged users */
 #define LL_SBI_XATTR_CACHE    0x80000 /* support for xattr cache */
 #define LL_SBI_LAYOUT_LOCK    0x20000 /* layout lock support */
 #define LL_SBI_USER_FID2PATH  0x40000 /* allow fid2path by unprivileged users */
 #define LL_SBI_XATTR_CACHE    0x80000 /* support for xattr cache */
+#define LL_SBI_NOROOTSQUASH  0x100000 /* do not apply root squash */
 
 #define LL_SBI_FLAGS {         \
        "nolck",        \
 
 #define LL_SBI_FLAGS {         \
        "nolck",        \
@@ -451,6 +452,7 @@ enum stats_track_type {
        "layout",       \
        "user_fid2path",\
        "xattr",        \
        "layout",       \
        "user_fid2path",\
        "xattr",        \
+       "norootsquash", \
 }
 
 #define RCE_HASHES      32
 }
 
 #define RCE_HASHES      32
@@ -549,6 +551,9 @@ struct ll_sb_info {
                                                 * clustred nfs */
        struct rmtacl_ctl_table   ll_rct;
        struct eacl_table         ll_et;
                                                 * clustred nfs */
        struct rmtacl_ctl_table   ll_rct;
        struct eacl_table         ll_et;
+
+       /* root squash */
+       struct root_squash_info   ll_squash;
 };
 
 #define LL_DEFAULT_MAX_RW_CHUNK      (32 * 1024 * 1024)
 };
 
 #define LL_DEFAULT_MAX_RW_CHUNK      (32 * 1024 * 1024)
@@ -885,6 +890,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
 void ll_finish_md_op_data(struct md_op_data *op_data);
 int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg);
 char *ll_get_fsname(struct super_block *sb, char *buf, int buflen);
 void ll_finish_md_op_data(struct md_op_data *op_data);
 int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg);
 char *ll_get_fsname(struct super_block *sb, char *buf, int buflen);
+void ll_compute_rootsquash_state(struct ll_sb_info *sbi);
 
 /* llite/llite_nfs.c */
 extern struct export_operations lustre_export_operations;
 
 /* llite/llite_nfs.c */
 extern struct export_operations lustre_export_operations;
index e3dda71..9b09581 100644 (file)
@@ -71,14 +71,14 @@ static struct ll_sb_info *ll_init_sbi(void)
        struct ll_sb_info *sbi = NULL;
        unsigned long pages;
        unsigned long lru_page_max;
        struct ll_sb_info *sbi = NULL;
        unsigned long pages;
        unsigned long lru_page_max;
-        struct sysinfo si;
-        class_uuid_t uuid;
-        int i;
-        ENTRY;
+       struct sysinfo si;
+       class_uuid_t uuid;
+       int i;
+       ENTRY;
 
 
-        OBD_ALLOC(sbi, sizeof(*sbi));
-        if (!sbi)
-                RETURN(NULL);
+       OBD_ALLOC_PTR(sbi);
+       if (sbi == NULL)
+               RETURN(NULL);
 
        spin_lock_init(&sbi->ll_lock);
        mutex_init(&sbi->ll_lco.lco_lock);
 
        spin_lock_init(&sbi->ll_lock);
        mutex_init(&sbi->ll_lco.lco_lock);
@@ -139,6 +139,12 @@ static struct ll_sb_info *ll_init_sbi(void)
        atomic_set(&sbi->ll_agl_total, 0);
        sbi->ll_flags |= LL_SBI_AGL_ENABLED;
 
        atomic_set(&sbi->ll_agl_total, 0);
        sbi->ll_flags |= LL_SBI_AGL_ENABLED;
 
+       /* root squash */
+       sbi->ll_squash.rsi_uid = 0;
+       sbi->ll_squash.rsi_gid = 0;
+       INIT_LIST_HEAD(&sbi->ll_squash.rsi_nosquash_nids);
+       init_rwsem(&sbi->ll_squash.rsi_sem);
+
        RETURN(sbi);
 }
 
        RETURN(sbi);
 }
 
@@ -151,6 +157,8 @@ static void ll_free_sbi(struct super_block *sb)
                spin_lock(&ll_sb_lock);
                list_del(&sbi->ll_list);
                spin_unlock(&ll_sb_lock);
                spin_lock(&ll_sb_lock);
                list_del(&sbi->ll_list);
                spin_unlock(&ll_sb_lock);
+               if (!list_empty(&sbi->ll_squash.rsi_nosquash_nids))
+                       cfs_free_nidlist(&sbi->ll_squash.rsi_nosquash_nids);
                OBD_FREE(sbi, sizeof(*sbi));
        }
        EXIT;
                OBD_FREE(sbi, sizeof(*sbi));
        }
        EXIT;
@@ -2733,3 +2741,41 @@ void ll_dirty_page_discard_warn(struct page *page, int ioret)
        if (buf != NULL)
                free_page((unsigned long)buf);
 }
        if (buf != NULL)
                free_page((unsigned long)buf);
 }
+
+/*
+ * Compute llite root squash state after a change of root squash
+ * configuration setting or add/remove of a lnet nid
+ */
+void ll_compute_rootsquash_state(struct ll_sb_info *sbi)
+{
+       struct root_squash_info *squash = &sbi->ll_squash;
+       int i;
+       bool matched;
+       lnet_process_id_t id;
+
+       /* Update norootsquash flag */
+       down_write(&squash->rsi_sem);
+       if (list_empty(&squash->rsi_nosquash_nids))
+               sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH;
+       else {
+               /* Do not apply root squash as soon as one of our NIDs is
+                * in the nosquash_nids list */
+               matched = false;
+               i = 0;
+               while (LNetGetId(i++, &id) != -ENOENT) {
+                       if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND)
+                               continue;
+                       if (cfs_match_nid(id.nid, &squash->rsi_nosquash_nids)) {
+                               matched = true;
+                               break;
+                       }
+               }
+               if (matched)
+                       sbi->ll_flags |= LL_SBI_NOROOTSQUASH;
+               else
+                       sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH;
+       }
+       up_write(&squash->rsi_sem);
+}
+
+
index 97cfc09..8595822 100644 (file)
@@ -831,6 +831,71 @@ static int ll_unstable_stats_seq_show(struct seq_file *m, void *v)
 }
 LPROC_SEQ_FOPS_RO(ll_unstable_stats);
 
 }
 LPROC_SEQ_FOPS_RO(ll_unstable_stats);
 
+static int ll_root_squash_seq_show(struct seq_file *m, void *v)
+{
+       struct super_block *sb = m->private;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       struct root_squash_info *squash = &sbi->ll_squash;
+
+       return seq_printf(m, "%u:%u\n", squash->rsi_uid, squash->rsi_gid);
+}
+
+static ssize_t ll_root_squash_seq_write(struct file *file,
+                                       const char __user *buffer,
+                                       size_t count, loff_t *off)
+{
+       struct seq_file *m = file->private_data;
+       struct super_block *sb = m->private;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       struct root_squash_info *squash = &sbi->ll_squash;
+
+       return lprocfs_wr_root_squash(buffer, count, squash,
+                                     ll_get_fsname(sb, NULL, 0));
+}
+LPROC_SEQ_FOPS(ll_root_squash);
+
+static int ll_nosquash_nids_seq_show(struct seq_file *m, void *v)
+{
+       struct super_block *sb = m->private;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       struct root_squash_info *squash = &sbi->ll_squash;
+       int len, rc;
+
+       down_read(&squash->rsi_sem);
+       if (!list_empty(&squash->rsi_nosquash_nids)) {
+               len = cfs_print_nidlist(m->buf + m->count, m->size - m->count,
+                                       &squash->rsi_nosquash_nids);
+               m->count += len;
+               rc = seq_printf(m, "\n");
+       } else {
+               rc = seq_printf(m, "NONE\n");
+       }
+       up_read(&squash->rsi_sem);
+
+       return rc;
+}
+
+static ssize_t ll_nosquash_nids_seq_write(struct file *file,
+                                         const char __user *buffer,
+                                         size_t count, loff_t *off)
+{
+       struct seq_file *m = file->private_data;
+       struct super_block *sb = m->private;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       struct root_squash_info *squash = &sbi->ll_squash;
+       int rc;
+
+       rc = lprocfs_wr_nosquash_nids(buffer, count, squash,
+                                     ll_get_fsname(sb, NULL, 0));
+       if (rc < 0)
+               return rc;
+
+       ll_compute_rootsquash_state(sbi);
+
+       return rc;
+}
+LPROC_SEQ_FOPS(ll_nosquash_nids);
+
 struct lprocfs_seq_vars lprocfs_llite_obd_vars[] = {
        { .name =       "uuid",
          .fops =       &ll_sb_uuid_fops                        },
 struct lprocfs_seq_vars lprocfs_llite_obd_vars[] = {
        { .name =       "uuid",
          .fops =       &ll_sb_uuid_fops                        },
@@ -892,6 +957,10 @@ struct lprocfs_seq_vars lprocfs_llite_obd_vars[] = {
          .fops =       &ll_xattr_cache_fops                    },
        { .name =       "unstable_stats",
          .fops =       &ll_unstable_stats_fops                 },
          .fops =       &ll_xattr_cache_fops                    },
        { .name =       "unstable_stats",
          .fops =       &ll_unstable_stats_fops                 },
+       { .name =       "root_squash",
+         .fops =       &ll_root_squash_fops                    },
+       { .name =       "nosquash_nids",
+         .fops =       &ll_nosquash_nids_fops                  },
        { 0 }
 };
 
        { 0 }
 };
 
index 8f4c86d..0c9ab85 100644 (file)
@@ -4369,12 +4369,7 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
 
        mdt_quota_fini(env, m);
 
 
        mdt_quota_fini(env, m);
 
-        cfs_free_nidlist(&m->mdt_nosquash_nids);
-        if (m->mdt_nosquash_str) {
-                OBD_FREE(m->mdt_nosquash_str, m->mdt_nosquash_strlen);
-                m->mdt_nosquash_str = NULL;
-                m->mdt_nosquash_strlen = 0;
-        }
+       cfs_free_nidlist(&m->mdt_squash.rsi_nosquash_nids);
 
         mdt_seq_fini(env, m);
         mdt_fld_fini(env, m);
 
         mdt_seq_fini(env, m);
         mdt_fld_fini(env, m);
@@ -4460,12 +4455,10 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
         m->mdt_capa_timeout = CAPA_TIMEOUT;
         m->mdt_capa_alg = CAPA_HMAC_ALG_SHA1;
         m->mdt_ck_timeout = CAPA_KEY_TIMEOUT;
         m->mdt_capa_timeout = CAPA_TIMEOUT;
         m->mdt_capa_alg = CAPA_HMAC_ALG_SHA1;
         m->mdt_ck_timeout = CAPA_KEY_TIMEOUT;
-        m->mdt_squash_uid = 0;
-        m->mdt_squash_gid = 0;
-        CFS_INIT_LIST_HEAD(&m->mdt_nosquash_nids);
-        m->mdt_nosquash_str = NULL;
-        m->mdt_nosquash_strlen = 0;
-       init_rwsem(&m->mdt_squash_sem);
+       m->mdt_squash.rsi_uid = 0;
+       m->mdt_squash.rsi_gid = 0;
+       INIT_LIST_HEAD(&m->mdt_squash.rsi_nosquash_nids);
+       init_rwsem(&m->mdt_squash.rsi_sem);
        spin_lock_init(&m->mdt_osfs_lock);
        m->mdt_osfs_age = cfs_time_shift_64(-1000);
        m->mdt_enable_remote_dir = 0;
        spin_lock_init(&m->mdt_osfs_lock);
        m->mdt_osfs_age = cfs_time_shift_64(-1000);
        m->mdt_enable_remote_dir = 0;
index bce5d12..116d98f 100644 (file)
@@ -219,12 +219,7 @@ struct mdt_device {
        spinlock_t                 mdt_osfs_lock;
 
         /* root squash */
        spinlock_t                 mdt_osfs_lock;
 
         /* root squash */
-        uid_t                      mdt_squash_uid;
-        gid_t                      mdt_squash_gid;
-        cfs_list_t                 mdt_nosquash_nids;
-        char                      *mdt_nosquash_str;
-        int                        mdt_nosquash_strlen;
-       struct rw_semaphore        mdt_squash_sem;
+       struct root_squash_info    mdt_squash;
 
         struct rename_stats        mdt_rename_stats;
        struct lu_fid              mdt_md_root_fid;
 
         struct rename_stats        mdt_rename_stats;
        struct lu_fid              mdt_md_root_fid;
index 1c60854..eb839a6 100644 (file)
@@ -95,28 +95,28 @@ static int match_nosquash_list(struct rw_semaphore *sem,
 static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid)
 {
        struct lu_ucred *ucred = mdt_ucred(info);
 static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid)
 {
        struct lu_ucred *ucred = mdt_ucred(info);
+       struct root_squash_info *squash = &info->mti_mdt->mdt_squash;
        ENTRY;
 
        LASSERT(ucred != NULL);
        ENTRY;
 
        LASSERT(ucred != NULL);
-       if (!info->mti_mdt->mdt_squash_uid || ucred->uc_fsuid)
+       if (!squash->rsi_uid || ucred->uc_fsuid)
                RETURN(0);
 
                RETURN(0);
 
-        if (match_nosquash_list(&info->mti_mdt->mdt_squash_sem,
-                                &info->mti_mdt->mdt_nosquash_nids,
-                                peernid)) {
-                CDEBUG(D_OTHER, "%s is in nosquash_nids list\n",
-                       libcfs_nid2str(peernid));
-                RETURN(0);
-        }
+       if (match_nosquash_list(&squash->rsi_sem,
+                               &squash->rsi_nosquash_nids,
+                               peernid)) {
+               CDEBUG(D_OTHER, "%s is in nosquash_nids list\n",
+                      libcfs_nid2str(peernid));
+               RETURN(0);
+       }
 
        CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n",
               libcfs_nid2str(peernid),
               ucred->uc_fsuid, ucred->uc_fsgid, ucred->uc_cap,
 
        CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n",
               libcfs_nid2str(peernid),
               ucred->uc_fsuid, ucred->uc_fsgid, ucred->uc_cap,
-              info->mti_mdt->mdt_squash_uid, info->mti_mdt->mdt_squash_gid,
-              0);
+              squash->rsi_uid, squash->rsi_gid, 0);
 
 
-       ucred->uc_fsuid = info->mti_mdt->mdt_squash_uid;
-       ucred->uc_fsgid = info->mti_mdt->mdt_squash_gid;
+       ucred->uc_fsuid = squash->rsi_uid;
+       ucred->uc_fsgid = squash->rsi_gid;
        ucred->uc_cap = 0;
        ucred->uc_suppgids[0] = -1;
        ucred->uc_suppgids[1] = -1;
        ucred->uc_cap = 0;
        ucred->uc_suppgids[0] = -1;
        ucred->uc_suppgids[1] = -1;
index 2603c79..70eba85 100644 (file)
@@ -688,169 +688,58 @@ static int lprocfs_wr_cos(struct file *file, const char __user *buffer,
         return count;
 }
 
         return count;
 }
 
-static int lprocfs_rd_root_squash(char *page, char **start, off_t off,
-                                  int count, int *eof, void *data)
+static int lprocfs_rd_mdt_root_squash(char *page, char **start, off_t off,
+                                     int count, int *eof, void *data)
 {
 {
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+       struct obd_device *obd = data;
+       struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+       struct root_squash_info *squash = &mdt->mdt_squash;
 
 
-        return snprintf(page, count, "%u:%u\n", mdt->mdt_squash_uid,
-                        mdt->mdt_squash_gid);
+       return snprintf(page, count, "%u:%u\n", squash->rsi_uid,
+                       squash->rsi_gid);
 }
 
 }
 
-static int safe_strtoul(const char *str, char **endp, unsigned long *res)
+static int lprocfs_wr_mdt_root_squash(struct file *file,
+                                     const char __user *buffer,
+                                     unsigned long count, void *data)
 {
 {
-        char n[24];
-
-        *res = simple_strtoul(str, endp, 0);
-        if (str == *endp)
-                return 1;
+       struct obd_device *obd = data;
+       struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+       struct root_squash_info *squash = &mdt->mdt_squash;
 
 
-        sprintf(n, "%lu", *res);
-        if (strncmp(n, str, *endp - str))
-                /* overflow */
-                return 1;
-        return 0;
+       return lprocfs_wr_root_squash(buffer, count, squash,
+                                     mdt_obd_name(mdt));
 }
 
 }
 
-static int lprocfs_wr_root_squash(struct file *file, const char __user *buffer,
-                                 unsigned long count, void *data)
+static int lprocfs_rd_mdt_nosquash_nids(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
 {
        struct obd_device *obd = data;
        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
 {
        struct obd_device *obd = data;
        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+       struct root_squash_info *squash = &mdt->mdt_squash;
        int rc;
        int rc;
-       char kernbuf[64], *tmp, *end, *errmsg;
-       unsigned long uid, gid;
-       int nouid, nogid;
-       ENTRY;
 
 
-       if (count >= sizeof(kernbuf)) {
-               errmsg = "string too long";
-               GOTO(failed_noprint, rc = -EINVAL);
-       }
-       if (copy_from_user(kernbuf, buffer, count)) {
-               errmsg = "bad address";
-               GOTO(failed_noprint, rc = -EFAULT);
-       }
-       kernbuf[count] = '\0';
+       down_read(&squash->rsi_sem);
+       if (!list_empty(&squash->rsi_nosquash_nids)) {
+               rc = cfs_print_nidlist(page, count, &squash->rsi_nosquash_nids);
+               rc += snprintf(page + rc, count - rc, "\n");
+       } else
+               rc = snprintf(page, count, "NONE\n");
+       up_read(&squash->rsi_sem);
 
 
-       nouid = nogid = 0;
-       if (safe_strtoul(kernbuf, &tmp, &uid)) {
-               uid = mdt->mdt_squash_uid;
-               nouid = 1;
-       }
-
-       /* skip ':' */
-       if (*tmp == ':') {
-               tmp++;
-               if (safe_strtoul(tmp, &end, &gid)) {
-                       gid = mdt->mdt_squash_gid;
-                       nogid = 1;
-               }
-       } else {
-               gid = mdt->mdt_squash_gid;
-               nogid = 1;
-       }
-
-       mdt->mdt_squash_uid = uid;
-       mdt->mdt_squash_gid = gid;
-
-       if (nouid && nogid) {
-               errmsg = "needs uid:gid format";
-               GOTO(failed, rc = -EINVAL);
-       }
-
-       LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
-                     mdt_obd_name(mdt),
-                     mdt->mdt_squash_uid,  mdt->mdt_squash_gid);
-       RETURN(count);
-
-failed:
-       CWARN("%s: failed to set root_squash to \"%s\", %s: rc %d\n",
-             mdt_obd_name(mdt), kernbuf, errmsg, rc);
-       RETURN(rc);
-failed_noprint:
-       CWARN("%s: failed to set root_squash due to %s: rc %d\n",
-             mdt_obd_name(mdt), errmsg, rc);
-       RETURN(rc);
+       return rc;
 }
 
 }
 
-static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
-                                    int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-
-        if (mdt->mdt_nosquash_str)
-                return snprintf(page, count, "%s\n", mdt->mdt_nosquash_str);
-        return snprintf(page, count, "NONE\n");
-}
-
-static int lprocfs_wr_nosquash_nids(struct file *file,
-                                   const char __user *buffer,
-                                   unsigned long count, void *data)
+static int lprocfs_wr_mdt_nosquash_nids(struct file *file,
+                                       const char __user *buffer,
+                                       unsigned long count, void *data)
 {
        struct obd_device *obd = data;
        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
 {
        struct obd_device *obd = data;
        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-       int rc;
-       char *kernbuf, *errmsg;
-       cfs_list_t tmp;
-       ENTRY;
-
-       OBD_ALLOC(kernbuf, count + 1);
-       if (kernbuf == NULL) {
-               errmsg = "no memory";
-               GOTO(failed, rc = -ENOMEM);
-       }
-       if (copy_from_user(kernbuf, buffer, count)) {
-               errmsg = "bad address";
-               GOTO(failed, rc = -EFAULT);
-       }
-       kernbuf[count] = '\0';
-
-       if (!strcmp(kernbuf, "NONE") || !strcmp(kernbuf, "clear")) {
-               /* empty string is special case */
-               down_write(&mdt->mdt_squash_sem);
-               if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
-                       cfs_free_nidlist(&mdt->mdt_nosquash_nids);
-                       OBD_FREE(mdt->mdt_nosquash_str,
-                                mdt->mdt_nosquash_strlen);
-                       mdt->mdt_nosquash_str = NULL;
-                       mdt->mdt_nosquash_strlen = 0;
-               }
-               up_write(&mdt->mdt_squash_sem);
-               LCONSOLE_INFO("%s: nosquash_nids is cleared\n",
-                             mdt_obd_name(mdt));
-               OBD_FREE(kernbuf, count + 1);
-               RETURN(count);
-       }
-
-       CFS_INIT_LIST_HEAD(&tmp);
-       if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) {
-               errmsg = "can't parse";
-               GOTO(failed, rc = -EINVAL);
-       }
+       struct root_squash_info *squash = &mdt->mdt_squash;
 
 
-       down_write(&mdt->mdt_squash_sem);
-       if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
-               cfs_free_nidlist(&mdt->mdt_nosquash_nids);
-               OBD_FREE(mdt->mdt_nosquash_str, mdt->mdt_nosquash_strlen);
-       }
-       mdt->mdt_nosquash_str = kernbuf;
-       mdt->mdt_nosquash_strlen = count + 1;
-       cfs_list_splice(&tmp, &mdt->mdt_nosquash_nids);
-
-       LCONSOLE_INFO("%s: nosquash_nids is set to %s\n",
-                     mdt_obd_name(mdt), kernbuf);
-       up_write(&mdt->mdt_squash_sem);
-       RETURN(count);
-
-failed:
-       CWARN("%s: failed to set nosquash_nids to \"%s\", %s: rc %d\n",
-             mdt_obd_name(mdt), kernbuf, errmsg, rc);
-       if (kernbuf)
-               OBD_FREE(kernbuf, count + 1);
-       RETURN(rc);
+       return lprocfs_wr_nosquash_nids(buffer, count, squash,
+                                       mdt_obd_name(mdt));
 }
 
 static int lprocfs_rd_mdt_som(char *page, char **start, off_t off,
 }
 
 static int lprocfs_rd_mdt_som(char *page, char **start, off_t off,
@@ -1011,11 +900,11 @@ static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
                                        NULL, NULL, 0 },
        { "commit_on_sharing",          lprocfs_rd_cos, lprocfs_wr_cos,
                                        NULL, NULL, 0 },
                                        NULL, NULL, 0 },
        { "commit_on_sharing",          lprocfs_rd_cos, lprocfs_wr_cos,
                                        NULL, NULL, 0 },
-       { "root_squash",                lprocfs_rd_root_squash,
-                                       lprocfs_wr_root_squash,
+       { "root_squash",                lprocfs_rd_mdt_root_squash,
+                                       lprocfs_wr_mdt_root_squash,
                                        NULL, NULL, 0 },
                                        NULL, NULL, 0 },
-       { "nosquash_nids",              lprocfs_rd_nosquash_nids,
-                                       lprocfs_wr_nosquash_nids,
+       { "nosquash_nids",              lprocfs_rd_mdt_nosquash_nids,
+                                       lprocfs_wr_mdt_nosquash_nids,
                                        NULL, NULL, 0 },
        { "som",                        lprocfs_rd_mdt_som,
                                        lprocfs_wr_mdt_som,
                                        NULL, NULL, 0 },
        { "som",                        lprocfs_rd_mdt_som,
                                        lprocfs_wr_mdt_som,
index 753dcfc..55ffe90 100644 (file)
@@ -3415,9 +3415,22 @@ static int mgs_write_log_param(const struct lu_env *env,
                if (rc)
                        GOTO(end, rc);
 
                if (rc)
                        GOTO(end, rc);
 
-                CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
+               /* Forbid direct update of llite root squash parameters.
+                * These parameters are indirectly set via the MDT settings.
+                * See (LU-1778) */
+               if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
+                   ((memcmp(tmp, "root_squash=", 12) == 0) ||
+                    (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
+                       LCONSOLE_ERROR("%s: root squash parameters can only "
+                               "be updated through MDT component\n",
+                               mti->mti_fsname);
+                       name_destroy(&cname);
+                       GOTO(end, rc = -EINVAL);
+               }
+
+               CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
 
 
-                /* Modify client */
+               /* Modify client */
                rc = name_create(&logname, mti->mti_fsname, "-client");
                if (rc) {
                        name_destroy(&cname);
                rc = name_create(&logname, mti->mti_fsname, "-client");
                if (rc) {
                        name_destroy(&cname);
@@ -3453,13 +3466,13 @@ static int mgs_write_log_param(const struct lu_env *env,
                                }
                        }
                }
                                }
                        }
                }
-                name_destroy(&logname);
-                name_destroy(&cname);
-                GOTO(end, rc);
-        }
+               name_destroy(&logname);
+               name_destroy(&cname);
+               GOTO(end, rc);
+       }
 
 
-        /* All mdt. params in proc */
-        if (class_match_param(ptr, PARAM_MDT, NULL) == 0) {
+       /* All mdt. params in proc */
+       if (class_match_param(ptr, PARAM_MDT, &tmp) == 0) {
                 int i;
                 __u32 idx;
 
                 int i;
                 __u32 idx;
 
@@ -3485,20 +3498,56 @@ static int mgs_write_log_param(const struct lu_env *env,
                                        goto active_err;
                                rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
                                                  logname, &mgi->mgi_bufs,
                                        goto active_err;
                                rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
                                                  logname, &mgi->mgi_bufs,
-                                                  logname, ptr);
-                                name_destroy(&logname);
-                                if (rc)
-                                        goto active_err;
-                        }
-                } else {
+                                                 logname, ptr);
+                               name_destroy(&logname);
+                               if (rc)
+                                       goto active_err;
+                       }
+               } else {
+                       if ((memcmp(tmp, "root_squash=", 12) == 0) ||
+                           (memcmp(tmp, "nosquash_nids=", 14) == 0)) {
+                               LCONSOLE_ERROR("%s: root squash parameters "
+                                       "cannot be applied to a single MDT\n",
+                                       mti->mti_fsname);
+                               GOTO(end, rc = -EINVAL);
+                       }
                        rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
                                          mti->mti_svname, &mgi->mgi_bufs,
                        rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
                                          mti->mti_svname, &mgi->mgi_bufs,
-                                          mti->mti_svname, ptr);
-                        if (rc)
-                                goto active_err;
-                }
-                GOTO(end, rc);
-        }
+                                         mti->mti_svname, ptr);
+                       if (rc)
+                               goto active_err;
+               }
+
+               /* root squash settings are also applied to llite
+                * config log (see LU-1778) */
+               if (rc == 0 &&
+                   ((memcmp(tmp, "root_squash=", 12) == 0) ||
+                    (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
+                       char *cname;
+                       char *ptr2;
+
+                       rc = name_create(&cname, mti->mti_fsname, "-client");
+                       if (rc)
+                               GOTO(end, rc);
+                       rc = name_create(&logname, mti->mti_fsname, "-client");
+                       if (rc) {
+                               name_destroy(&cname);
+                               GOTO(end, rc);
+                       }
+                       rc = name_create(&ptr2, PARAM_LLITE, tmp);
+                       if (rc) {
+                               name_destroy(&cname);
+                               name_destroy(&logname);
+                               GOTO(end, rc);
+                       }
+                       rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
+                                         &mgi->mgi_bufs, cname, ptr2);
+                       name_destroy(&ptr2);
+                       name_destroy(&logname);
+                       name_destroy(&cname);
+               }
+               GOTO(end, rc);
+       }
 
        /* All mdd., ost. and osd. params in proc */
        if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
 
        /* All mdd., ost. and osd. params in proc */
        if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
index 938cb7a..dcc00a8 100644 (file)
@@ -3748,4 +3748,137 @@ int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);
+
+int lprocfs_wr_root_squash(const char __user *buffer, unsigned long count,
+                          struct root_squash_info *squash, char *name)
+{
+       int rc;
+       char kernbuf[64], *tmp, *errmsg;
+       unsigned long uid, gid;
+       ENTRY;
+
+       if (count >= sizeof(kernbuf)) {
+               errmsg = "string too long";
+               GOTO(failed_noprint, rc = -EINVAL);
+       }
+       if (copy_from_user(kernbuf, buffer, count)) {
+               errmsg = "bad address";
+               GOTO(failed_noprint, rc = -EFAULT);
+       }
+       kernbuf[count] = '\0';
+
+       /* look for uid gid separator */
+       tmp = strchr(kernbuf, ':');
+       if (tmp == NULL) {
+               errmsg = "needs uid:gid format";
+               GOTO(failed, rc = -EINVAL);
+       }
+       *tmp = '\0';
+       tmp++;
+
+       /* parse uid */
+       if (kstrtoul(kernbuf, 0, &uid) != 0) {
+               errmsg = "bad uid";
+               GOTO(failed, rc = -EINVAL);
+       }
+
+       /* parse gid */
+       if (kstrtoul(tmp, 0, &gid) != 0) {
+               errmsg = "bad gid";
+               GOTO(failed, rc = -EINVAL);
+       }
+
+       squash->rsi_uid = uid;
+       squash->rsi_gid = gid;
+
+       LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
+                     name, squash->rsi_uid, squash->rsi_gid);
+       RETURN(count);
+
+failed:
+       if (tmp != NULL) {
+               tmp--;
+               *tmp = ':';
+       }
+       CWARN("%s: failed to set root_squash to \"%s\", %s, rc = %d\n",
+             name, kernbuf, errmsg, rc);
+       RETURN(rc);
+failed_noprint:
+       CWARN("%s: failed to set root_squash due to %s, rc = %d\n",
+             name, errmsg, rc);
+       RETURN(rc);
+}
+EXPORT_SYMBOL(lprocfs_wr_root_squash);
+
+
+int lprocfs_wr_nosquash_nids(const char __user *buffer, unsigned long count,
+                            struct root_squash_info *squash, char *name)
+{
+       int rc;
+       char *kernbuf = NULL;
+       char *errmsg;
+       struct list_head tmp;
+       ENTRY;
+
+       if (count > 4096) {
+               errmsg = "string too long";
+               GOTO(failed, rc = -EINVAL);
+       }
+
+       OBD_ALLOC(kernbuf, count + 1);
+       if (kernbuf == NULL) {
+               errmsg = "no memory";
+               GOTO(failed, rc = -ENOMEM);
+       }
+       if (copy_from_user(kernbuf, buffer, count)) {
+               errmsg = "bad address";
+               GOTO(failed, rc = -EFAULT);
+       }
+       kernbuf[count] = '\0';
+
+       if (count > 0 && kernbuf[count - 1] == '\n')
+               kernbuf[count - 1] = '\0';
+
+       if (strcmp(kernbuf, "NONE") == 0 || strcmp(kernbuf, "clear") == 0) {
+               /* empty string is special case */
+               down_write(&squash->rsi_sem);
+               if (!list_empty(&squash->rsi_nosquash_nids))
+                       cfs_free_nidlist(&squash->rsi_nosquash_nids);
+               up_write(&squash->rsi_sem);
+               LCONSOLE_INFO("%s: nosquash_nids is cleared\n", name);
+               OBD_FREE(kernbuf, count + 1);
+               RETURN(count);
+       }
+
+       INIT_LIST_HEAD(&tmp);
+       if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) {
+               errmsg = "can't parse";
+               GOTO(failed, rc = -EINVAL);
+       }
+       LCONSOLE_INFO("%s: nosquash_nids set to %s\n",
+                     name, kernbuf);
+       OBD_FREE(kernbuf, count + 1);
+       kernbuf = NULL;
+
+       down_write(&squash->rsi_sem);
+       if (!list_empty(&squash->rsi_nosquash_nids))
+               cfs_free_nidlist(&squash->rsi_nosquash_nids);
+       list_splice(&tmp, &squash->rsi_nosquash_nids);
+       up_write(&squash->rsi_sem);
+
+       RETURN(count);
+
+failed:
+       if (kernbuf) {
+               CWARN("%s: failed to set nosquash_nids to \"%s\", %s rc = %d\n",
+                     name, kernbuf, errmsg, rc);
+               OBD_FREE(kernbuf, count + 1);
+       } else {
+               CWARN("%s: failed to set nosquash_nids due to %s rc = %d\n",
+                     name, errmsg, rc);
+       }
+       RETURN(rc);
+}
+EXPORT_SYMBOL(lprocfs_wr_nosquash_nids);
+
 #endif /* LPROCFS*/
 #endif /* LPROCFS*/
index cb29b9a..8595230 100644 (file)
@@ -2587,16 +2587,30 @@ run_test 42 "allow client/server mount/unmount with invalid config param"
 
 test_43() {
        [ $UID -ne 0 -o $RUNAS_ID -eq 0 ] && skip_env "run as root"
 
 test_43() {
        [ $UID -ne 0 -o $RUNAS_ID -eq 0 ] && skip_env "run as root"
+
+       ID1=${ID1:-501}
+       USER1=$(cat /etc/passwd | grep :$ID1:$ID1: | cut -d: -f1)
+       [ -z "$USER1" ] && skip_env "missing user with uid=$ID1 gid=$ID1" &&
+               return
+
        setup
        chmod ugo+x $DIR || error "chmod 0 failed"
        set_conf_param_and_check mds                                    \
                "lctl get_param -n mdt.$FSNAME-MDT0000.root_squash"     \
                "$FSNAME.mdt.root_squash"                               \
                "0:0"
        setup
        chmod ugo+x $DIR || error "chmod 0 failed"
        set_conf_param_and_check mds                                    \
                "lctl get_param -n mdt.$FSNAME-MDT0000.root_squash"     \
                "$FSNAME.mdt.root_squash"                               \
                "0:0"
+       wait_update $HOSTNAME                                           \
+               "lctl get_param -n llite.${FSNAME}*.root_squash"        \
+               "0:0" ||
+               error "check llite root_squash failed!"
        set_conf_param_and_check mds                                    \
                "lctl get_param -n mdt.$FSNAME-MDT0000.nosquash_nids"   \
                "$FSNAME.mdt.nosquash_nids"                             \
                "NONE"
        set_conf_param_and_check mds                                    \
                "lctl get_param -n mdt.$FSNAME-MDT0000.nosquash_nids"   \
                "$FSNAME.mdt.nosquash_nids"                             \
                "NONE"
+       wait_update $HOSTNAME                                           \
+               "lctl get_param -n llite.${FSNAME}*.nosquash_nids"      \
+               "NONE" ||
+               error "check llite nosquash_nids failed!"
 
     #
     # create set of test files
 
     #
     # create set of test files
@@ -2612,6 +2626,10 @@ test_43() {
     chmod go-rwx $DIR/$tdir-rootdir   || error "chmod 3 failed"
     touch $DIR/$tdir-rootdir/tfile-1  || error "touch failed"
 
     chmod go-rwx $DIR/$tdir-rootdir   || error "chmod 3 failed"
     touch $DIR/$tdir-rootdir/tfile-1  || error "touch failed"
 
+       echo "777" > $DIR/$tfile-user1file || error "write 7 failed"
+       chmod go-rw $DIR/$tfile-user1file  || error "chmod 7 failed"
+       chown $ID1.$ID1 $DIR/$tfile-user1file || error "chown failed"
+
        #
        # check root_squash:
        #   set root squash UID:GID to RUNAS_ID
        #
        # check root_squash:
        #   set root squash UID:GID to RUNAS_ID
@@ -2621,6 +2639,10 @@ test_43() {
                "lctl get_param -n mdt.$FSNAME-MDT0000.root_squash"     \
                "$FSNAME.mdt.root_squash"                               \
                "$RUNAS_ID:$RUNAS_ID"
                "lctl get_param -n mdt.$FSNAME-MDT0000.root_squash"     \
                "$FSNAME.mdt.root_squash"                               \
                "$RUNAS_ID:$RUNAS_ID"
+       wait_update $HOSTNAME                                           \
+               "lctl get_param -n llite.${FSNAME}*.root_squash"        \
+               "$RUNAS_ID:$RUNAS_ID" ||
+               error "check llite root_squash failed!"
 
     ST=$(stat -c "%n: owner uid %u (%A)" $DIR/$tfile-userfile)
     dd if=$DIR/$tfile-userfile 1>/dev/null 2>/dev/null || \
 
     ST=$(stat -c "%n: owner uid %u (%A)" $DIR/$tfile-userfile)
     dd if=$DIR/$tfile-userfile 1>/dev/null 2>/dev/null || \
@@ -2628,7 +2650,7 @@ test_43() {
     echo "$ST: root read permission is granted - ok"
 
     echo "444" | \
     echo "$ST: root read permission is granted - ok"
 
     echo "444" | \
-    dd conv=notrunc if=$DIR/$tfile-userfile 1>/dev/null 2>/dev/null || \
+    dd conv=notrunc of=$DIR/$tfile-userfile 1>/dev/null 2>/dev/null || \
         error "$ST: root write permission is denied"
     echo "$ST: root write permission is granted - ok"
 
         error "$ST: root write permission is denied"
     echo "$ST: root write permission is granted - ok"
 
@@ -2651,6 +2673,31 @@ test_43() {
         error "$ST: root create permission is granted"
     echo "$ST: root create permission is denied - ok"
 
         error "$ST: root create permission is granted"
     echo "$ST: root create permission is denied - ok"
 
+
+       # LU-1778
+       # check root_squash is enforced independently
+       # of client cache content
+       #
+       # access file by USER1, keep access open
+       # root should be denied access to user file
+
+       runas -u $ID1 tail -f $DIR/$tfile-user1file 1>/dev/null 2>&1 &
+       pid=$!
+       sleep 1
+
+       ST=$(stat -c "%n: owner uid %u (%A)" $DIR/$tfile-user1file)
+       dd if=$DIR/$tfile-user1file 1>/dev/null 2>&1 &&
+           { kill $pid; error "$ST: root read permission is granted"; }
+       echo "$ST: root read permission is denied - ok"
+
+       echo "777" | \
+       dd conv=notrunc of=$DIR/$tfile-user1file 1>/dev/null 2>&1 &&
+           { kill $pid; error "$ST: root write permission is granted"; }
+       echo "$ST: root write permission is denied - ok"
+
+       kill $pid
+       wait $pid
+
        #
        # check nosquash_nids:
        #   put client's NID into nosquash_nids list,
        #
        # check nosquash_nids:
        #   put client's NID into nosquash_nids list,
@@ -2663,6 +2710,10 @@ test_43() {
                "lctl get_param -n mdt.$FSNAME-MDT0000.nosquash_nids"   \
                "$FSNAME-MDTall.mdt.nosquash_nids"                      \
                "$NIDLIST"
                "lctl get_param -n mdt.$FSNAME-MDT0000.nosquash_nids"   \
                "$FSNAME-MDTall.mdt.nosquash_nids"                      \
                "$NIDLIST"
+       wait_update $HOSTNAME                                           \
+               "lctl get_param -n llite.${FSNAME}*.nosquash_nids"      \
+               "$NIDLIST" ||
+               error "check llite nosquash_nids failed!"
 
     ST=$(stat -c "%n: owner uid %u (%A)" $DIR/$tfile-rootfile)
     dd if=$DIR/$tfile-rootfile 1>/dev/null 2>/dev/null || \
 
     ST=$(stat -c "%n: owner uid %u (%A)" $DIR/$tfile-rootfile)
     dd if=$DIR/$tfile-rootfile 1>/dev/null 2>/dev/null || \