Whamcloud - gitweb
LU-9413 llite: llite.stat_blocksize param for fixed st_blksize 69/26869/11
authorAndrew Perepechko <andrew.perepechko@seagate.com>
Thu, 27 Apr 2017 16:01:23 +0000 (19:01 +0300)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 24 May 2017 07:33:50 +0000 (07:33 +0000)
llite.stat_blocksize is added to allow configurable st_blksize
for stat(2). The latter is treated incorrectly by some
applications. For example, glibc pre-2.25 uses this value for
stdio buffering which completely ruins performance with random
reads.

The patch changes the behaviour of getattr rather than inode
initialization so that change of the setting causes immediate
effect without the need of reclaiming existing inodes.

The patch is similar to the patch from bz # 12739 by Aurelien
Degremont.

Change-Id: Ic6ab3fea40940892b740b8e87347dbb361619e8b
Signed-off-by: Andrew Perepechko <andrew.perepechko@seagate.com>
Reviewed-on: https://review.whamcloud.com/26869
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Alexander Zarochentsev <alexander.zarochentsev@seagate.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/lproc_llite.c

index 7aa00c9..edd438c 100644 (file)
@@ -3688,7 +3688,7 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
        stat->atime = inode->i_atime;
        stat->mtime = inode->i_mtime;
        stat->ctime = inode->i_ctime;
-       stat->blksize = 1 << inode->i_blkbits;
+       stat->blksize = sbi->ll_stat_blksize ?: 1 << inode->i_blkbits;
 
        stat->nlink = inode->i_nlink;
        stat->size = i_size_read(inode);
index bab7e68..28f42d2 100644 (file)
@@ -531,6 +531,9 @@ struct ll_sb_info {
        /* root squash */
        struct root_squash_info   ll_squash;
        struct path               ll_mnt;
+
+       /* st_blksize returned by stat(2), when non-zero */
+       unsigned int              ll_stat_blksize;
 };
 
 /*
index 63ccf88..90ca5e4 100644 (file)
@@ -68,6 +68,37 @@ static int ll_blksize_seq_show(struct seq_file *m, void *v)
 }
 LPROC_SEQ_FOPS_RO(ll_blksize);
 
+static int ll_stat_blksize_seq_show(struct seq_file *m, void *v)
+{
+       struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private);
+
+       seq_printf(m, "%u\n", sbi->ll_stat_blksize);
+
+       return 0;
+}
+
+static ssize_t ll_stat_blksize_seq_write(struct file *file,
+                                        const char __user *buffer,
+                                        size_t count, loff_t *off)
+{
+       struct seq_file *m = file->private_data;
+       struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private);
+       __s64 val;
+       int rc;
+
+       rc = lprocfs_str_to_s64(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       if (val != 0 && (val < PAGE_SIZE || (val & (val - 1))) != 0)
+               return -ERANGE;
+
+       sbi->ll_stat_blksize = val;
+
+       return count;
+}
+LPROC_SEQ_FOPS(ll_stat_blksize);
+
 static int ll_kbytestotal_seq_show(struct seq_file *m, void *v)
 {
        struct super_block *sb = m->private;
@@ -1022,6 +1053,8 @@ struct lprocfs_vars lprocfs_llite_obd_vars[] = {
          .fops =       &ll_site_stats_fops                     },
        { .name =       "blocksize",
          .fops =       &ll_blksize_fops                        },
+       { .name =       "stat_blocksize",
+         .fops =       &ll_stat_blksize_fops                   },
        { .name =       "kbytestotal",
          .fops =       &ll_kbytestotal_fops                    },
        { .name =       "kbytesfree",