diff options
Diffstat (limited to 'fs/cachefiles/namei.c')
| -rw-r--r-- | fs/cachefiles/namei.c | 128 | 
1 files changed, 79 insertions, 49 deletions
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 42c7fafc8bf..5bf2b41e66d 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -35,44 +35,42 @@ void __cachefiles_printk_object(struct cachefiles_object *object,  	struct fscache_cookie *cookie;  	unsigned keylen, loop; -	printk(KERN_ERR "%sobject: OBJ%x\n", -	       prefix, object->fscache.debug_id); -	printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n", -	       prefix, fscache_object_states[object->fscache.state], +	pr_err("%sobject: OBJ%x\n", prefix, object->fscache.debug_id); +	pr_err("%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n", +	       prefix, object->fscache.state->name,  	       object->fscache.flags, work_busy(&object->fscache.work), -	       object->fscache.events, -	       object->fscache.event_mask & FSCACHE_OBJECT_EVENTS_MASK); -	printk(KERN_ERR "%sops=%u inp=%u exc=%u\n", +	       object->fscache.events, object->fscache.event_mask); +	pr_err("%sops=%u inp=%u exc=%u\n",  	       prefix, object->fscache.n_ops, object->fscache.n_in_progress,  	       object->fscache.n_exclusive); -	printk(KERN_ERR "%sparent=%p\n", +	pr_err("%sparent=%p\n",  	       prefix, object->fscache.parent);  	spin_lock(&object->fscache.lock);  	cookie = object->fscache.cookie;  	if (cookie) { -		printk(KERN_ERR "%scookie=%p [pr=%p nd=%p fl=%lx]\n", +		pr_err("%scookie=%p [pr=%p nd=%p fl=%lx]\n",  		       prefix,  		       object->fscache.cookie,  		       object->fscache.cookie->parent,  		       object->fscache.cookie->netfs_data,  		       object->fscache.cookie->flags); -		if (keybuf) +		if (keybuf && cookie->def)  			keylen = cookie->def->get_key(cookie->netfs_data, keybuf,  						      CACHEFILES_KEYBUF_SIZE);  		else  			keylen = 0;  	} else { -		printk(KERN_ERR "%scookie=NULL\n", prefix); +		pr_err("%scookie=NULL\n", prefix);  		keylen = 0;  	}  	spin_unlock(&object->fscache.lock);  	if (keylen) { -		printk(KERN_ERR "%skey=[%u] '", prefix, keylen); +		pr_err("%skey=[%u] '", prefix, keylen);  		for (loop = 0; loop < keylen; loop++) -			printk("%02x", keybuf[loop]); -		printk("'\n"); +			pr_cont("%02x", keybuf[loop]); +		pr_cont("'\n");  	}  } @@ -128,17 +126,15 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,  found_dentry:  	kdebug("preemptive burial: OBJ%x [%s] %p",  	       object->fscache.debug_id, -	       fscache_object_states[object->fscache.state], +	       object->fscache.state->name,  	       dentry); -	if (object->fscache.state < FSCACHE_OBJECT_DYING) { -		printk(KERN_ERR "\n"); -		printk(KERN_ERR "CacheFiles: Error:" -		       " Can't preemptively bury live object\n"); +	if (fscache_object_is_live(&object->fscache)) { +		pr_err("\n"); +		pr_err("Error: Can't preemptively bury live object\n");  		cachefiles_printk_object(object, NULL);  	} else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { -		printk(KERN_ERR "CacheFiles: Error:" -		       " Object already preemptively buried\n"); +		pr_err("Error: Object already preemptively buried\n");  	}  	write_unlock(&cache->active_lock); @@ -161,7 +157,7 @@ try_again:  	write_lock(&cache->active_lock);  	if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) { -		printk(KERN_ERR "CacheFiles: Error: Object already active\n"); +		pr_err("Error: Object already active\n");  		cachefiles_printk_object(object, NULL);  		BUG();  	} @@ -193,10 +189,9 @@ try_again:  	/* an old object from a previous incarnation is hogging the slot - we  	 * need to wait for it to be destroyed */  wait_for_old_object: -	if (xobject->fscache.state < FSCACHE_OBJECT_DYING) { -		printk(KERN_ERR "\n"); -		printk(KERN_ERR "CacheFiles: Error:" -		       " Unexpected object collision\n"); +	if (fscache_object_is_live(&object->fscache)) { +		pr_err("\n"); +		pr_err("Error: Unexpected object collision\n");  		cachefiles_printk_object(object, xobject);  		BUG();  	} @@ -242,9 +237,8 @@ wait_for_old_object:  		}  		if (timeout <= 0) { -			printk(KERN_ERR "\n"); -			printk(KERN_ERR "CacheFiles: Error: Overlong" -			       " wait for old active object to go away\n"); +			pr_err("\n"); +			pr_err("Error: Overlong wait for old active object to go away\n");  			cachefiles_printk_object(object, xobject);  			goto requeue;  		} @@ -275,6 +269,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,  				  bool preemptive)  {  	struct dentry *grave, *trap; +	struct path path, path_to_graveyard;  	char nbuffer[8 + 8 + 1];  	int ret; @@ -287,10 +282,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,  	/* non-directories can just be unlinked */  	if (!S_ISDIR(rep->d_inode->i_mode)) {  		_debug("unlink stale object"); -		ret = vfs_unlink(dir->d_inode, rep); -		if (preemptive) -			cachefiles_mark_object_buried(cache, rep); +		path.mnt = cache->mnt; +		path.dentry = dir; +		ret = security_path_unlink(&path, rep); +		if (ret < 0) { +			cachefiles_io_error(cache, "Unlink security error"); +		} else { +			ret = vfs_unlink(dir->d_inode, rep, NULL); + +			if (preemptive) +				cachefiles_mark_object_buried(cache, rep); +		}  		mutex_unlock(&dir->d_inode->i_mutex); @@ -379,12 +382,23 @@ try_again:  	}  	/* attempt the rename */ -	ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave); -	if (ret != 0 && ret != -ENOMEM) -		cachefiles_io_error(cache, "Rename failed with error %d", ret); +	path.mnt = cache->mnt; +	path.dentry = dir; +	path_to_graveyard.mnt = cache->mnt; +	path_to_graveyard.dentry = cache->graveyard; +	ret = security_path_rename(&path, rep, &path_to_graveyard, grave, 0); +	if (ret < 0) { +		cachefiles_io_error(cache, "Rename security error %d", ret); +	} else { +		ret = vfs_rename(dir->d_inode, rep, +				 cache->graveyard->d_inode, grave, NULL, 0); +		if (ret != 0 && ret != -ENOMEM) +			cachefiles_io_error(cache, +					    "Rename failed with error %d", ret); -	if (preemptive) -		cachefiles_mark_object_buried(cache, rep); +		if (preemptive) +			cachefiles_mark_object_buried(cache, rep); +	}  	unlock_rename(cache->graveyard, dir);  	dput(grave); @@ -448,6 +462,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,  {  	struct cachefiles_cache *cache;  	struct dentry *dir, *next = NULL; +	struct path path;  	unsigned long start;  	const char *name;  	int ret, nlen; @@ -458,6 +473,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,  	cache = container_of(parent->fscache.cache,  			     struct cachefiles_cache, cache); +	path.mnt = cache->mnt;  	ASSERT(parent->dentry);  	ASSERT(parent->dentry->d_inode); @@ -511,6 +527,10 @@ lookup_again:  			if (ret < 0)  				goto create_error; +			path.dentry = dir; +			ret = security_path_mkdir(&path, next, 0); +			if (ret < 0) +				goto create_error;  			start = jiffies;  			ret = vfs_mkdir(dir->d_inode, next, 0);  			cachefiles_hist(cachefiles_mkdir_histogram, start); @@ -523,7 +543,7 @@ lookup_again:  			       next, next->d_inode, next->d_inode->i_ino);  		} else if (!S_ISDIR(next->d_inode->i_mode)) { -			kerror("inode %lu is not a directory", +			pr_err("inode %lu is not a directory",  			       next->d_inode->i_ino);  			ret = -ENOBUFS;  			goto error; @@ -536,8 +556,12 @@ lookup_again:  			if (ret < 0)  				goto create_error; +			path.dentry = dir; +			ret = security_path_mknod(&path, next, S_IFREG, 0); +			if (ret < 0) +				goto create_error;  			start = jiffies; -			ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); +			ret = vfs_create(dir->d_inode, next, S_IFREG, true);  			cachefiles_hist(cachefiles_create_histogram, start);  			if (ret < 0)  				goto create_error; @@ -550,7 +574,7 @@ lookup_again:  		} else if (!S_ISDIR(next->d_inode->i_mode) &&  			   !S_ISREG(next->d_inode->i_mode)  			   ) { -			kerror("inode %lu is not a file or directory", +			pr_err("inode %lu is not a file or directory",  			       next->d_inode->i_ino);  			ret = -ENOBUFS;  			goto error; @@ -616,7 +640,8 @@ lookup_again:  		 * (this is used to keep track of culling, and atimes are only  		 * updated by read, write and readdir but not lookup or  		 * open) */ -		touch_atime(cache->mnt, next); +		path.dentry = next; +		touch_atime(&path);  	}  	/* open a file interface onto a data file */ @@ -692,6 +717,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,  {  	struct dentry *subdir;  	unsigned long start; +	struct path path;  	int ret;  	_enter(",,%s", dirname); @@ -719,6 +745,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,  		_debug("attempt mkdir"); +		path.mnt = cache->mnt; +		path.dentry = dir; +		ret = security_path_mkdir(&path, subdir, 0700); +		if (ret < 0) +			goto mkdir_error;  		ret = vfs_mkdir(dir->d_inode, subdir, 0700);  		if (ret < 0)  			goto mkdir_error; @@ -737,14 +768,13 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,  	ASSERT(subdir->d_inode);  	if (!S_ISDIR(subdir->d_inode->i_mode)) { -		kerror("%s is not a directory", dirname); +		pr_err("%s is not a directory", dirname);  		ret = -EIO;  		goto check_error;  	}  	ret = -EPERM; -	if (!subdir->d_inode->i_op || -	    !subdir->d_inode->i_op->setxattr || +	if (!subdir->d_inode->i_op->setxattr ||  	    !subdir->d_inode->i_op->getxattr ||  	    !subdir->d_inode->i_op->lookup ||  	    !subdir->d_inode->i_op->mkdir || @@ -765,13 +795,13 @@ check_error:  mkdir_error:  	mutex_unlock(&dir->d_inode->i_mutex);  	dput(subdir); -	kerror("mkdir %s failed with error %d", dirname, ret); +	pr_err("mkdir %s failed with error %d", dirname, ret);  	return ERR_PTR(ret);  lookup_error:  	mutex_unlock(&dir->d_inode->i_mutex);  	ret = PTR_ERR(subdir); -	kerror("Lookup %s failed with error %d", dirname, ret); +	pr_err("Lookup %s failed with error %d", dirname, ret);  	return ERR_PTR(ret);  nomem_d_alloc: @@ -800,7 +830,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,  	//       dir->d_name.len, dir->d_name.len, dir->d_name.name, filename);  	/* look up the victim */ -	mutex_lock_nested(&dir->d_inode->i_mutex, 1); +	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);  	start = jiffies;  	victim = lookup_one_len(filename, dir, strlen(filename)); @@ -861,7 +891,7 @@ lookup_error:  	if (ret == -EIO) {  		cachefiles_io_error(cache, "Lookup failed");  	} else if (ret != -ENOMEM) { -		kerror("Internal error: %d", ret); +		pr_err("Internal error: %d", ret);  		ret = -EIO;  	} @@ -920,7 +950,7 @@ error:  	}  	if (ret != -ENOMEM) { -		kerror("Internal error: %d", ret); +		pr_err("Internal error: %d", ret);  		ret = -EIO;  	}  | 
