@@ -860,6 +860,7 @@ int ll_file_open(struct inode *inode, struct file *file)
if (rc)
goto out_och_free;
}
+
rc = pcc_file_open(inode, file);
if (rc)
goto out_och_free;
@@ -1787,7 +1788,7 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
* from PCC cache automatically.
*/
result = pcc_file_write_iter(iocb, from, &cached);
- if (cached && result != -ENOSPC)
+ if (cached && result != -ENOSPC && result != -EDQUOT)
return result;
/* NB: we can't do direct IO for tiny writes because they use the page
@@ -71,11 +71,16 @@ static struct ll_sb_info *ll_init_sbi(void)
unsigned long pages;
unsigned long lru_page_max;
struct sysinfo si;
+ int rc;
int i;
sbi = kzalloc(sizeof(*sbi), GFP_NOFS);
if (!sbi)
- return NULL;
+ return ERR_PTR(-ENOMEM);
+
+ rc = pcc_super_init(&sbi->ll_pcc_super);
+ if (rc < 0)
+ goto out_sbi;
spin_lock_init(&sbi->ll_lock);
mutex_init(&sbi->ll_lco.lco_lock);
@@ -89,8 +94,8 @@ static struct ll_sb_info *ll_init_sbi(void)
sbi->ll_cache = cl_cache_init(lru_page_max);
if (!sbi->ll_cache) {
- kfree(sbi);
- return NULL;
+ rc = -ENOMEM;
+ goto out_pcc;
}
sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32,
@@ -128,12 +133,16 @@ static struct ll_sb_info *ll_init_sbi(void)
sbi->ll_squash.rsi_gid = 0;
INIT_LIST_HEAD(&sbi->ll_squash.rsi_nosquash_nids);
spin_lock_init(&sbi->ll_squash.rsi_lock);
- pcc_super_init(&sbi->ll_pcc_super);
/* Per-filesystem file heat */
sbi->ll_heat_decay_weight = SBI_DEFAULT_HEAT_DECAY_WEIGHT;
sbi->ll_heat_period_second = SBI_DEFAULT_HEAT_PERIOD_SECOND;
return sbi;
+out_pcc:
+ pcc_super_fini(&sbi->ll_pcc_super);
+out_sbi:
+ kfree(sbi);
+ return ERR_PTR(rc);
}
static void ll_free_sbi(struct super_block *sb)
@@ -990,8 +999,8 @@ int ll_fill_super(struct super_block *sb)
/* client additional sb info */
sbi = ll_init_sbi();
lsi->lsi_llsbi = sbi;
- if (!sbi) {
- err = -ENOMEM;
+ if (IS_ERR(sbi)) {
+ err = PTR_ERR(sbi);
goto out_free;
}
@@ -1120,7 +1129,7 @@ void ll_put_super(struct super_block *sb)
int next, force = 1, rc = 0;
long ccc_count;
- if (!sbi)
+ if (IS_ERR(sbi))
goto out_no_sbi;
CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm);
@@ -835,7 +835,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
goto out;
}
- rc = pcc_inode_create(dataset, &op_data->op_fid2,
+ rc = pcc_inode_create(parent->i_sb, dataset, &op_data->op_fid2,
&pca->pca_dentry);
if (rc) {
retval = ERR_PTR(rc);
@@ -113,10 +113,20 @@
struct kmem_cache *pcc_inode_slab;
-void pcc_super_init(struct pcc_super *super)
+int pcc_super_init(struct pcc_super *super)
{
+ struct cred *cred;
+
+ super->pccs_cred = cred = prepare_creds();
+ if (!cred)
+ return -ENOMEM;
+
+ /* Never override disk quota limits or use reserved space */
+ cap_lower(cred->cap_effective, CAP_SYS_RESOURCE);
spin_lock_init(&super->pccs_lock);
INIT_LIST_HEAD(&super->pccs_datasets);
+
+ return 0;
}
/**
@@ -251,7 +261,7 @@ struct pcc_dataset *
return 0;
}
-void pcc_super_fini(struct pcc_super *super)
+static void pcc_remove_datasets(struct pcc_super *super)
{
struct pcc_dataset *dataset, *tmp;
@@ -262,6 +272,12 @@ void pcc_super_fini(struct pcc_super *super)
}
}
+void pcc_super_fini(struct pcc_super *super)
+{
+ pcc_remove_datasets(super);
+ put_cred(super->pccs_cred);
+}
+
static bool pathname_is_valid(const char *pathname)
{
/* Needs to be absolute path */
@@ -380,7 +396,7 @@ int pcc_cmd_handle(char *buffer, unsigned long count,
rc = pcc_dataset_del(super, cmd->pccc_pathname);
break;
case PCC_CLEAR_ALL:
- pcc_super_fini(super);
+ pcc_remove_datasets(super);
break;
default:
rc = -EINVAL;
@@ -463,6 +479,11 @@ static int pcc_fid2dataset_path(char *buf, int sz, struct lu_fid *fid)
PFID(fid));
}
+static inline const struct cred *pcc_super_cred(struct super_block *sb)
+{
+ return ll_s2sbi(sb)->ll_pcc_super.pccs_cred;
+}
+
void pcc_file_init(struct pcc_file *pccf)
{
pccf->pccf_file = NULL;
@@ -503,7 +524,9 @@ int pcc_file_open(struct inode *inode, struct file *file)
dname = &path->dentry->d_name;
CDEBUG(D_CACHE, "opening pcc file '%.*s'\n", dname->len,
dname->name);
- pcc_file = dentry_open(path, file->f_flags, current_cred());
+
+ pcc_file = dentry_open(path, file->f_flags,
+ pcc_super_cred(inode->i_sb));
if (IS_ERR_OR_NULL(pcc_file)) {
rc = pcc_file ? PTR_ERR(pcc_file) : -EINVAL;
pcc_inode_put(pcci);
@@ -652,6 +675,7 @@ int pcc_inode_setattr(struct inode *inode, struct iattr *attr,
bool *cached)
{
int rc = 0;
+ const struct cred *old_cred;
struct iattr attr2 = *attr;
struct dentry *pcc_dentry;
struct pcc_inode *pcci;
@@ -667,11 +691,13 @@ int pcc_inode_setattr(struct inode *inode, struct iattr *attr,
attr2.ia_valid = attr->ia_valid & (ATTR_SIZE | ATTR_ATIME |
ATTR_ATIME_SET | ATTR_MTIME | ATTR_MTIME_SET |
- ATTR_CTIME);
+ ATTR_CTIME | ATTR_UID | ATTR_GID);
pcci = ll_i2pcci(inode);
pcc_dentry = pcci->pcci_path.dentry;
inode_lock(pcc_dentry->d_inode);
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc = pcc_dentry->d_inode->i_op->setattr(pcc_dentry, &attr2);
+ revert_creds(old_cred);
inode_unlock(pcc_dentry->d_inode);
pcc_io_fini(inode);
@@ -681,6 +707,7 @@ int pcc_inode_setattr(struct inode *inode, struct iattr *attr,
int pcc_inode_getattr(struct inode *inode, bool *cached)
{
struct ll_inode_info *lli = ll_i2info(inode);
+ const struct cred *old_cred;
struct kstat stat;
s64 atime;
s64 mtime;
@@ -696,8 +723,10 @@ int pcc_inode_getattr(struct inode *inode, bool *cached)
if (!*cached)
return 0;
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc = vfs_getattr(&ll_i2pcci(inode)->pcci_path, &stat,
STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
+ revert_creds(old_cred);
if (rc)
goto out;
@@ -1113,14 +1142,14 @@ static int __pcc_inode_create(struct pcc_dataset *dataset,
pcc_fid2dataset_path(path, MAX_PCC_DATABASE_PATH, fid);
- base = pcc_mkdir_p(dataset->pccd_path.dentry, path, 0700);
+ base = pcc_mkdir_p(dataset->pccd_path.dentry, path, 0);
if (IS_ERR(base)) {
rc = PTR_ERR(base);
goto out;
}
snprintf(path, MAX_PCC_DATABASE_PATH, DFID_NOBRACE, PFID(fid));
- child = pcc_create(base, path, 0600);
+ child = pcc_create(base, path, 0);
if (IS_ERR(child)) {
rc = PTR_ERR(child);
goto out_base;
@@ -1134,18 +1163,44 @@ static int __pcc_inode_create(struct pcc_dataset *dataset,
return rc;
}
-int pcc_inode_create(struct pcc_dataset *dataset, struct lu_fid *fid,
- struct dentry **pcc_dentry)
+/* TODO: Set the project ID for PCC copy */
+int pcc_inode_store_ugpid(struct dentry *dentry, kuid_t uid, kgid_t gid)
+{
+ struct inode *inode = dentry->d_inode;
+ struct iattr attr;
+ int rc;
+
+ attr.ia_valid = ATTR_UID | ATTR_GID;
+ attr.ia_uid = uid;
+ attr.ia_gid = gid;
+
+ inode_lock(inode);
+ rc = notify_change(dentry, &attr, NULL);
+ inode_unlock(inode);
+
+ return rc;
+}
+
+int pcc_inode_create(struct super_block *sb, struct pcc_dataset *dataset,
+ struct lu_fid *fid, struct dentry **pcc_dentry)
{
- return __pcc_inode_create(dataset, fid, pcc_dentry);
+ const struct cred *old_cred;
+ int rc;
+
+ old_cred = override_creds(pcc_super_cred(sb));
+ rc = __pcc_inode_create(dataset, fid, pcc_dentry);
+ revert_creds(old_cred);
+ return rc;
}
int pcc_inode_create_fini(struct pcc_dataset *dataset, struct inode *inode,
struct dentry *pcc_dentry)
{
+ const struct cred *old_cred;
struct pcc_inode *pcci;
int rc = 0;
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
pcc_inode_lock(inode);
LASSERT(!ll_i2pcci(inode));
pcci = kmem_cache_zalloc(pcc_inode_slab, GFP_NOFS);
@@ -1154,6 +1209,11 @@ int pcc_inode_create_fini(struct pcc_dataset *dataset, struct inode *inode,
goto out_unlock;
}
+ rc = pcc_inode_store_ugpid(pcc_dentry, old_cred->suid,
+ old_cred->sgid);
+ if (rc)
+ goto out_unlock;
+
pcc_inode_init(pcci, ll_i2info(inode));
pcc_inode_attach_init(dataset, pcci, pcc_dentry, LU_PCC_READWRITE);
/* Set the layout generation of newly created file with 0 */
@@ -1172,6 +1232,10 @@ int pcc_inode_create_fini(struct pcc_dataset *dataset, struct inode *inode,
}
pcc_inode_unlock(inode);
+ revert_creds(old_cred);
+ if (rc)
+ kmem_cache_free(pcc_inode_slab, pcci);
+
return rc;
}
@@ -1253,6 +1317,7 @@ int pcc_readwrite_attach(struct file *file, struct inode *inode,
struct pcc_dataset *dataset;
struct ll_inode_info *lli = ll_i2info(inode);
struct pcc_inode *pcci;
+ const struct cred *old_cred;
struct dentry *dentry;
struct file *pcc_filp;
struct path path;
@@ -1267,9 +1332,12 @@ int pcc_readwrite_attach(struct file *file, struct inode *inode,
if (!dataset)
return -ENOENT;
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc = __pcc_inode_create(dataset, &lli->lli_fid, &dentry);
- if (rc)
+ if (rc) {
+ revert_creds(old_cred);
goto out_dataset_put;
+ }
path.mnt = dataset->pccd_path.mnt;
path.dentry = dentry;
@@ -1277,9 +1345,15 @@ int pcc_readwrite_attach(struct file *file, struct inode *inode,
current_cred());
if (IS_ERR_OR_NULL(pcc_filp)) {
rc = pcc_filp ? PTR_ERR(pcc_filp) : -EINVAL;
+ revert_creds(old_cred);
goto out_dentry;
}
+ rc = pcc_inode_store_ugpid(dentry, old_cred->uid, old_cred->gid);
+ revert_creds(old_cred);
+ if (rc)
+ goto out_fput;
+
rc = pcc_copy_data(file, pcc_filp);
if (rc)
goto out_fput;
@@ -1306,7 +1380,9 @@ int pcc_readwrite_attach(struct file *file, struct inode *inode,
if (rc) {
int rc2;
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc2 = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL);
+ revert_creds(old_cred);
if (rc2)
CWARN("failed to unlink PCC file, rc = %d\n", rc2);
@@ -1322,13 +1398,14 @@ int pcc_readwrite_attach_fini(struct file *file, struct inode *inode,
bool attached)
{
struct ll_inode_info *lli = ll_i2info(inode);
+ const struct cred *old_cred;
struct pcc_inode *pcci;
u32 gen2;
pcc_inode_lock(inode);
pcci = ll_i2pcci(inode);
lli->lli_pcc_state &= ~PCC_STATE_FL_ATTACHING;
- if ((rc || lease_broken)) {
+ if (rc || lease_broken) {
if (attached && pcci)
pcc_inode_put(pcci);
@@ -1357,7 +1434,9 @@ int pcc_readwrite_attach_fini(struct file *file, struct inode *inode,
out_put:
if (rc) {
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
pcc_inode_remove(pcci);
+ revert_creds(old_cred);
pcc_inode_put(pcci);
}
out_unlock:
@@ -53,8 +53,12 @@ struct pcc_dataset {
};
struct pcc_super {
- spinlock_t pccs_lock; /* Protect pccs_datasets */
- struct list_head pccs_datasets; /* List of datasets */
+ /* Protect pccs_datasets */
+ spinlock_t pccs_lock;
+ /* List of datasets */
+ struct list_head pccs_datasets;
+ /* creds of process who forced instantiation of super block */
+ const struct cred *pccs_cred;
};
struct pcc_inode {
@@ -108,7 +112,7 @@ struct pcc_cmd {
} u;
};
-void pcc_super_init(struct pcc_super *super);
+int pcc_super_init(struct pcc_super *super);
void pcc_super_fini(struct pcc_super *super);
int pcc_cmd_handle(char *buffer, unsigned long count,
struct pcc_super *super);
@@ -141,10 +145,10 @@ int pcc_fsync(struct file *file, loff_t start, loff_t end,
int pcc_fault(struct vm_area_struct *mva, struct vm_fault *vmf, bool *cached);
int pcc_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
bool *cached);
-int pcc_inode_create(struct pcc_dataset *dataset, struct lu_fid *fid,
- struct dentry **pcc_dentry);
+int pcc_inode_create(struct super_block *sb, struct pcc_dataset *dataset,
+ struct lu_fid *fid, struct dentry **pcc_dentry);
int pcc_inode_create_fini(struct pcc_dataset *dataset, struct inode *inode,
- struct dentry *pcc_dentry);
+ struct dentry *pcc_dentry);
struct pcc_dataset *pcc_dataset_get(struct pcc_super *super, u32 projid,
u32 archive_id);
void pcc_dataset_put(struct pcc_dataset *dataset);