- 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;
- }
-
- /* whether we allow setuid/setgid */
- if ((!lp->lrp_setuid && setuid) || (!lp->lrp_setgid && setgid)) {
- OBD_FREE(xperm, sizeof(*xperm));
- spin_unlock(&racl->ra_lock);
- return 0;
- }
-
- /* traverse xperm list */
- list_for_each_entry(xp, &lp->lrp_setxid_perms, list) {
- if (xp->uid == current->fsuid &&
- xp->gid == current->fsgid) {
- if (xp->perm != mperm->mrp_perm) {
- /* actually this should not happen */
- CWARN("perm changed: %o => %o\n",
- xp->perm, mperm->mrp_perm);
- xp->perm = mperm->mrp_perm;
- }
- OBD_FREE(xperm, sizeof(*xperm));
- spin_unlock(&racl->ra_lock);
- return 0;
- }
- }
-
- /* finally insert this xperm */
- xperm->uid = current->fsuid;
- xperm->gid = current->fsgid;
- xperm->perm = mperm->mrp_perm;
- list_add(&xperm->list, &lp->lrp_setxid_perms);
-
- spin_unlock(&racl->ra_lock);
- return 0;
-}
-
-/*
- * remote_acl semaphore must be held by caller
- */
-static
-int remote_acl_update_locked(struct remote_acl *racl,
- struct mds_remote_perm *mperm)
-{
- struct lustre_remote_perm *lperm;
- struct remote_perm_setxid *xperm;
- int setuid = 0, setgid = 0;
-
- might_sleep();
-
- if (current->uid != mperm->mrp_auth_uid) {
- CERROR("current uid %u while authenticated as %u\n",
- current->uid, mperm->mrp_auth_uid);
- return -EINVAL;