- ldlm_policy_data_t policy = { .l_extent = {attr->ia_size,
- OBD_OBJECT_EOF } };
- struct lustre_handle lockh = { 0 };
- int err, ast_flags = 0;
- /* XXX when we fix the AST intents to pass the discard-range
- * XXX extent, make ast_flags always LDLM_AST_DISCARD_DATA
- * XXX here. */
- if (attr->ia_size == 0)
- ast_flags = LDLM_AST_DISCARD_DATA;
-
- rc = ll_extent_lock(NULL, inode, lsm, LCK_PW, &policy, &lockh,
- ast_flags, &ll_i2sbi(inode)->ll_seek_stime);
-
- if (rc != 0)
- RETURN(rc);
-
- down(&lli->lli_size_sem);
- lli->lli_size_pid = current->pid;
- rc = vmtruncate(inode, attr->ia_size);
- if (rc != 0) {
- LASSERT(atomic_read(&lli->lli_size_sem.count) <= 0);
- lli->lli_size_pid = 0;
- up(&lli->lli_size_sem);
- }
-
- err = ll_extent_unlock(NULL, inode, lsm, LCK_PW, &lockh);
- if (err) {
- CERROR("ll_extent_unlock failed: %d\n", err);
- if (!rc)
- rc = err;
- }
- } else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET | ATTR_UID | ATTR_GID)) {
- struct obdo *oa = NULL;
-
- CDEBUG(D_INODE, "set mtime on OST inode %lu to %lu\n",
- inode->i_ino, LTIME_S(attr->ia_mtime));
-
- oa = obdo_alloc();
- if (oa == NULL)
- RETURN(-ENOMEM);
-
- oa->o_id = lsm->lsm_object_id;
- oa->o_gr = lsm->lsm_object_gr;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
-
- /* adding uid and gid, needed for quota */
- if (ia_valid & ATTR_UID) {
- oa->o_uid = inode->i_uid;
- oa->o_valid |= OBD_MD_FLUID;
- }
-
- if (ia_valid & ATTR_GID) {
- oa->o_gid = inode->i_gid;
- oa->o_valid |= OBD_MD_FLGID;
- }
-
- *(obdo_id(oa)) = lli->lli_id;
- oa->o_valid |= OBD_MD_FLIFID;
-
- obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
- OBD_MD_FLMTIME | OBD_MD_FLCTIME);
- rc = obd_setattr(sbi->ll_dt_exp, oa, lsm, NULL);
- obdo_free(oa);
- if (rc)
- CERROR("obd_setattr fails: rc = %d\n", rc);
- }
-
- RETURN(rc);
-}
-
-int ll_setattr(struct dentry *de, struct iattr *attr)
-{
- LASSERT(de->d_inode);
- return ll_setattr_raw(de->d_inode, attr);
-}
-
-int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
- unsigned long max_age)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct obd_statfs obd_osfs;
- int rc;
- ENTRY;
-
- rc = obd_statfs(class_exp2obd(sbi->ll_md_exp), osfs, max_age);
- if (rc) {
- CERROR("obd_statfs fails: rc = %d\n", rc);
- RETURN(rc);
- }
-
- osfs->os_type = sb->s_magic;
-
- CDEBUG(D_SUPER, "MDC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
- osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files);
-
- rc = obd_statfs(class_exp2obd(sbi->ll_dt_exp), &obd_osfs, max_age);
- if (rc) {
- CERROR("obd_statfs fails: rc = %d\n", rc);
- RETURN(rc);
- }
-
- CDEBUG(D_SUPER, "OSC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
- obd_osfs.os_bavail, obd_osfs.os_blocks, obd_osfs.os_ffree,
- obd_osfs.os_files);
-
- osfs->os_blocks = obd_osfs.os_blocks;
- osfs->os_bfree = obd_osfs.os_bfree;
- osfs->os_bavail = obd_osfs.os_bavail;
-
- /* If we don't have as many objects free on the OST as inodes
- * on the MDS, we reduce the total number of inodes to
- * compensate, so that the "inodes in use" number is correct.
- */
- if (obd_osfs.os_ffree < osfs->os_ffree) {
- osfs->os_files = (osfs->os_files - osfs->os_ffree) +
- obd_osfs.os_ffree;
- osfs->os_ffree = obd_osfs.os_ffree;
- }
-
- RETURN(rc);
-}
-
-int ll_statfs(struct super_block *sb, struct kstatfs *sfs)
-{
- struct obd_statfs osfs;
- int rc;
-
- CDEBUG(D_VFSTRACE, "VFS Op: superblock %p\n", sb);
- lprocfs_counter_incr(ll_s2sbi(sb)->ll_stats, LPROC_LL_STAFS);
-
- /* For now we will always get up-to-date statfs values, but in the
- * future we may allow some amount of caching on the client (e.g.
- * from QOS or lprocfs updates). */
- rc = ll_statfs_internal(sb, &osfs, jiffies - 1);
- if (rc)
- return rc;
-
- statfs_unpack(sfs, &osfs);
-
- if (sizeof(sfs->f_blocks) == 4) {
- while (osfs.os_blocks > ~0UL) {
- sfs->f_bsize <<= 1;
-
- osfs.os_blocks >>= 1;
- osfs.os_bfree >>= 1;
- osfs.os_bavail >>= 1;
- }
- }
-
- sfs->f_blocks = osfs.os_blocks;
- sfs->f_bfree = osfs.os_bfree;
- sfs->f_bavail = osfs.os_bavail;
-
- return 0;
-}
-
-
-/********************************
- * remote acl *
- ********************************/
-
-static struct remote_acl *remote_acl_alloc(void)
-{
- struct remote_acl *racl;
- int i;
-
- OBD_ALLOC(racl, sizeof(*racl));
- if (!racl)
- return NULL;
-
- spin_lock_init(&racl->ra_lock);
- init_MUTEX(&racl->ra_update_sem);
-
- for (i = 0; i < REMOTE_ACL_HASHSIZE; i++)
- INIT_LIST_HEAD(&racl->ra_perm_cache[i]);
-
- return racl;
-}
-
-/*
- * caller should guarantee no race here.
- */
-static void remote_perm_flush_xperms(struct lustre_remote_perm *perm)
-{
- struct remote_perm_setxid *xperm;
-
- while (!list_empty(&perm->lrp_setxid_perms)) {
- xperm = list_entry(perm->lrp_setxid_perms.next,
- struct remote_perm_setxid,
- list);
- list_del(&xperm->list);
- OBD_FREE(xperm, sizeof(*xperm));
- }
-}
-
-/*
- * caller should guarantee no race here.
- */
-static void remote_acl_flush(struct remote_acl *racl)
-{
- struct list_head *head;
- struct lustre_remote_perm *perm, *tmp;
- int i;
-
- for (i = 0; i < REMOTE_ACL_HASHSIZE; i++) {
- head = &racl->ra_perm_cache[i];
-
- list_for_each_entry_safe(perm, tmp, head, lrp_list) {
- remote_perm_flush_xperms(perm);
- list_del(&perm->lrp_list);
- OBD_FREE(perm, sizeof(*perm));
- }
- }
-}
-
-static void remote_acl_free(struct remote_acl *racl)
-{
- if (!racl)
- return;
-
- down(&racl->ra_update_sem);
- spin_lock(&racl->ra_lock);
- remote_acl_flush(racl);
- spin_unlock(&racl->ra_lock);
- up(&racl->ra_update_sem);
-
- OBD_FREE(racl, sizeof(*racl));
-}
-
-static inline int remote_acl_hashfunc(__u32 id)
-{
- return (id & (REMOTE_ACL_HASHSIZE - 1));
-}
-
-static
-int __remote_acl_check(struct remote_acl *racl, unsigned int *perm)
-{
- struct list_head *head;
- struct lustre_remote_perm *lperm;
- struct remote_perm_setxid *xperm;
- int found = 0, rc = -ENOENT;
-
- LASSERT(racl);
- head = &racl->ra_perm_cache[remote_acl_hashfunc(current->uid)];
- spin_lock(&racl->ra_lock);
-
- list_for_each_entry(lperm, head, lrp_list) {
- if (lperm->lrp_auth_uid == current->uid) {
- found = 1;
- break;
- }
- }
-
- if (!found)
- goto out;
-
- if (lperm->lrp_auth_uid == current->fsuid &&
- lperm->lrp_auth_gid == current->fsgid) {
- if (lperm->lrp_valid) {
- *perm = lperm->lrp_perm;
- rc = 0;
- }
- goto out;
- } else if ((!lperm->lrp_setuid &&
- lperm->lrp_auth_uid != current->fsuid) ||
- (!lperm->lrp_setgid &&
- lperm->lrp_auth_gid != current->fsgid)) {
- *perm = 0;
- rc = 0;
- goto out;
- }
-
- list_for_each_entry(xperm, &lperm->lrp_setxid_perms, list) {
- if (xperm->uid == current->fsuid &&
- xperm->gid == current->fsgid) {
- *perm = xperm->perm;
- rc = 0;
- goto out;
- }
- }
-
-out:
- spin_unlock(&racl->ra_lock);
- return rc;
-}
-
-static
-int __remote_acl_update(struct remote_acl *racl,
- struct mds_remote_perm *mperm,
- struct lustre_remote_perm *lperm,
- struct remote_perm_setxid *xperm)
-{
- struct list_head *head;
- struct lustre_remote_perm *lp;
- struct remote_perm_setxid *xp;
- int found = 0, setuid = 0, setgid = 0;
-
- LASSERT(racl);
- LASSERT(mperm);
- LASSERT(lperm);
- LASSERT(current->uid == mperm->mrp_auth_uid);
-
- if (current->fsuid != mperm->mrp_auth_uid)
- setuid = 1;
- if (current->fsgid != mperm->mrp_auth_gid)
- setgid = 1;
-
- head = &racl->ra_perm_cache[remote_acl_hashfunc(current->uid)];
- spin_lock(&racl->ra_lock);
-
- list_for_each_entry(lp, head, lrp_list) {
- if (lp->lrp_auth_uid == current->uid) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- OBD_FREE(lperm, sizeof(*lperm));
-
- if (!lp->lrp_valid && !setuid && !setgid) {
- lp->lrp_perm = mperm->mrp_perm;
- lp->lrp_valid = 1;
- }
-
- /* sanity check for changes of setxid rules */
- if ((lp->lrp_setuid != 0) != (mperm->mrp_allow_setuid != 0)) {
- CWARN("setuid changes: %d => %d\n",
- (lp->lrp_setuid != 0),
- (mperm->mrp_allow_setuid != 0));
- lp->lrp_setuid = (mperm->mrp_allow_setuid != 0);
- }
-
- if ((lp->lrp_setgid != 0) != (mperm->mrp_allow_setgid != 0)) {
- CWARN("setgid changes: %d => %d\n",
- (lp->lrp_setgid != 0),
- (mperm->mrp_allow_setgid != 0));
- lp->lrp_setgid = (mperm->mrp_allow_setgid != 0);
- }
-
- if (!lp->lrp_setuid && !lp->lrp_setgid &&
- !list_empty(&lp->lrp_setxid_perms)) {
- remote_perm_flush_xperms(lp);
- }
- } else {
- /* initialize lperm and linked into hashtable
- */
- INIT_LIST_HEAD(&lperm->lrp_setxid_perms);
- lperm->lrp_auth_uid = mperm->mrp_auth_uid;
- lperm->lrp_auth_gid = mperm->mrp_auth_gid;
- lperm->lrp_setuid = (mperm->mrp_allow_setuid != 0);
- lperm->lrp_setgid = (mperm->mrp_allow_setgid != 0);
- list_add(&lperm->lrp_list, head);
-
- if (!setuid && !setgid) {
- /* in this case, i'm the authenticated user,
- * and mrp_perm is for me.
- */
- lperm->lrp_perm = mperm->mrp_perm;
- lperm->lrp_valid = 1;
- spin_unlock(&racl->ra_lock);
-
- if (xperm)
- OBD_FREE(xperm, sizeof(*xperm));
- return 0;
- }
-
- lp = lperm;
- /* fall through */
- }
-
- LASSERT(lp->lrp_setuid || lp->lrp_setgid ||
- list_empty(&lp->lrp_setxid_perms));
-
- /* if no xperm supplied, we are all done here */
- if (!xperm) {
- spin_unlock(&racl->ra_lock);
- return 0;
- }