Whamcloud - gitweb
LU-9555 quota: df should return projid-specific values
[fs/lustre-release.git] / lustre / llite / llite_lib.c
index 45b2128..3744aa2 100644 (file)
@@ -129,11 +129,13 @@ static struct ll_sb_info *ll_init_sbi(void)
        if (sbi->ll_cache == NULL)
                GOTO(out_destroy_ra, rc = -ENOMEM);
 
-       sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32,
-                                                   SBI_DEFAULT_READ_AHEAD_MAX);
+       sbi->ll_ra_info.ra_max_pages =
+               min(pages / 32, SBI_DEFAULT_READ_AHEAD_MAX);
+       sbi->ll_ra_info.ra_max_pages_per_file =
+               min(sbi->ll_ra_info.ra_max_pages / 4,
+                   SBI_DEFAULT_READ_AHEAD_PER_FILE_MAX);
        sbi->ll_ra_info.ra_async_pages_per_file_threshold =
                                sbi->ll_ra_info.ra_max_pages_per_file;
-       sbi->ll_ra_info.ra_max_pages = sbi->ll_ra_info.ra_max_pages_per_file;
        sbi->ll_ra_info.ra_max_read_ahead_whole_pages = -1;
        atomic_set(&sbi->ll_ra_info.ra_async_inflight, 0);
 
@@ -276,7 +278,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
                                   OBD_CONNECT2_LSOM |
                                   OBD_CONNECT2_ASYNC_DISCARD |
                                   OBD_CONNECT2_PCC |
-                                  OBD_CONNECT2_CRUSH;
+                                  OBD_CONNECT2_CRUSH | OBD_CONNECT2_LSEEK |
+                                  OBD_CONNECT2_GETATTR_PFID;
 
 #ifdef HAVE_LRU_RESIZE_SUPPORT
         if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
@@ -474,7 +477,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
                                  OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO |
                                  OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK;
        data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD |
-                                  OBD_CONNECT2_INC_XID;
+                                  OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK;
 
        if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM))
                data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM;
@@ -2034,7 +2037,15 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
                            attr->ia_valid & ATTR_SIZE) {
                                xvalid |= OP_XVALID_FLAGS;
                                flags = LUSTRE_ENCRYPT_FL;
-                               if (attr->ia_size & ~PAGE_MASK) {
+                               /* Call to ll_io_zero_page is not necessary if
+                                * truncating on PAGE_SIZE boundary, because
+                                * whole pages will be wiped.
+                                * In case of Direct IO, all we need is to set
+                                * new size.
+                                */
+                               if (attr->ia_size & ~PAGE_MASK &&
+                                   !(attr->ia_valid & ATTR_FILE &&
+                                     attr->ia_file->f_flags & O_DIRECT)) {
                                        pgoff_t offset =
                                                attr->ia_size & (PAGE_SIZE - 1);
 
@@ -2194,6 +2205,52 @@ out:
        RETURN(rc);
 }
 
+static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs)
+{
+       struct if_quotactl qctl = {
+               .qc_cmd = LUSTRE_Q_GETQUOTA,
+               .qc_type = PRJQUOTA,
+               .qc_valid = QC_GENERAL,
+       };
+       u64 limit, curblock;
+       int ret;
+
+       qctl.qc_id = ll_i2info(inode)->lli_projid;
+       ret = quotactl_ioctl(ll_i2sbi(inode), &qctl);
+       if (ret) {
+               /* ignore errors if project ID does not have
+                * a quota limit or feature unsupported.
+                */
+               if (ret == -ESRCH || ret == -EOPNOTSUPP)
+                       ret = 0;
+               return ret;
+       }
+
+       limit = ((qctl.qc_dqblk.dqb_bsoftlimit ?
+                qctl.qc_dqblk.dqb_bsoftlimit :
+                qctl.qc_dqblk.dqb_bhardlimit) * 1024) / sfs->f_bsize;
+       if (limit && sfs->f_blocks > limit) {
+               curblock = (qctl.qc_dqblk.dqb_curspace +
+                               sfs->f_bsize - 1) / sfs->f_bsize;
+               sfs->f_blocks = limit;
+               sfs->f_bfree = sfs->f_bavail =
+                       (sfs->f_blocks > curblock) ?
+                       (sfs->f_blocks - curblock) : 0;
+       }
+
+       limit = qctl.qc_dqblk.dqb_isoftlimit ?
+               qctl.qc_dqblk.dqb_isoftlimit :
+               qctl.qc_dqblk.dqb_ihardlimit;
+       if (limit && sfs->f_files > limit) {
+               sfs->f_files = limit;
+               sfs->f_ffree = (sfs->f_files >
+                       qctl.qc_dqblk.dqb_curinodes) ?
+                       (sfs->f_files - qctl.qc_dqblk.dqb_curinodes) : 0;
+       }
+
+       return 0;
+}
+
 int ll_statfs(struct dentry *de, struct kstatfs *sfs)
 {
        struct super_block *sb = de->d_sb;
@@ -2230,6 +2287,8 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs)
        sfs->f_bavail = osfs.os_bavail;
        sfs->f_fsid.val[0] = (__u32)fsid;
        sfs->f_fsid.val[1] = (__u32)(fsid >> 32);
+       if (ll_i2info(de->d_inode)->lli_projid)
+               return ll_statfs_project(de->d_inode, sfs);
 
        ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STATFS,
                           ktime_us_delta(ktime_get(), kstart));
@@ -2900,7 +2959,9 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
                if (namelen > ll_i2sbi(i1)->ll_namelen)
                        return ERR_PTR(-ENAMETOOLONG);
 
-               if (!lu_name_is_valid_2(name, namelen))
+               /* "/" is not valid name, but it's allowed */
+               if (!lu_name_is_valid_2(name, namelen) &&
+                   strncmp("/", name, namelen) != 0)
                        return ERR_PTR(-EINVAL);
        }