Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
[deliverable/linux.git] / fs / libfs.c
index dcaf972cbf1b6d81f29e17d2a1fccd259a794777..62baa0387d6e03869e726b89ffaddccce4fc090c 100644 (file)
@@ -327,77 +327,35 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
 }
 
 /**
- * simple_setsize - handle core mm and vfs requirements for file size change
- * @inode: inode
- * @newsize: new file size
- *
- * Returns 0 on success, -error on failure.
- *
- * simple_setsize must be called with inode_mutex held.
- *
- * simple_setsize will check that the requested new size is OK (see
- * inode_newsize_ok), and then will perform the necessary i_size update
- * and pagecache truncation (if necessary). It will be typically be called
- * from the filesystem's setattr function when ATTR_SIZE is passed in.
- *
- * The inode itself must have correct permissions and attributes to allow
- * i_size to be changed, this function then just checks that the new size
- * requested is valid.
- *
- * In the case of simple in-memory filesystems with inodes stored solely
- * in the inode cache, and file data in the pagecache, nothing more needs
- * to be done to satisfy a truncate request. Filesystems with on-disk
- * blocks for example will need to free them in the case of truncate, in
- * that case it may be easier not to use simple_setsize (but each of its
- * components will likely be required at some point to update pagecache
- * and inode etc).
- */
-int simple_setsize(struct inode *inode, loff_t newsize)
-{
-       loff_t oldsize;
-       int error;
-
-       error = inode_newsize_ok(inode, newsize);
-       if (error)
-               return error;
-
-       oldsize = inode->i_size;
-       i_size_write(inode, newsize);
-       truncate_pagecache(inode, oldsize, newsize);
-
-       return error;
-}
-EXPORT_SYMBOL(simple_setsize);
-
-/**
- * simple_setattr - setattr for simple in-memory filesystem
+ * simple_setattr - setattr for simple filesystem
  * @dentry: dentry
  * @iattr: iattr structure
  *
  * Returns 0 on success, -error on failure.
  *
- * simple_setattr implements setattr for an in-memory filesystem which
- * does not store its own file data or metadata (eg. uses the page cache
- * and inode cache as its data store).
+ * simple_setattr is a simple ->setattr implementation without a proper
+ * implementation of size changes.
+ *
+ * It can either be used for in-memory filesystems or special files
+ * on simple regular filesystems.  Anything that needs to change on-disk
+ * or wire state on size changes needs its own setattr method.
  */
 int simple_setattr(struct dentry *dentry, struct iattr *iattr)
 {
        struct inode *inode = dentry->d_inode;
        int error;
 
+       WARN_ON_ONCE(inode->i_op->truncate);
+
        error = inode_change_ok(inode, iattr);
        if (error)
                return error;
 
-       if (iattr->ia_valid & ATTR_SIZE) {
-               error = simple_setsize(inode, iattr->ia_size);
-               if (error)
-                       return error;
-       }
-
-       generic_setattr(inode, iattr);
-
-       return error;
+       if (iattr->ia_valid & ATTR_SIZE)
+               truncate_setsize(inode, iattr->ia_size);
+       setattr_copy(inode, iattr);
+       mark_inode_dirty(inode);
+       return 0;
 }
 EXPORT_SYMBOL(simple_setattr);
 
@@ -955,6 +913,35 @@ int generic_file_fsync(struct file *file, int datasync)
 }
 EXPORT_SYMBOL(generic_file_fsync);
 
+/**
+ * generic_check_addressable - Check addressability of file system
+ * @blocksize_bits:    log of file system block size
+ * @num_blocks:                number of blocks in file system
+ *
+ * Determine whether a file system with @num_blocks blocks (and a
+ * block size of 2**@blocksize_bits) is addressable by the sector_t
+ * and page cache of the system.  Return 0 if so and -EFBIG otherwise.
+ */
+int generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)
+{
+       u64 last_fs_block = num_blocks - 1;
+       u64 last_fs_page =
+               last_fs_block >> (PAGE_CACHE_SHIFT - blocksize_bits);
+
+       if (unlikely(num_blocks == 0))
+               return 0;
+
+       if ((blocksize_bits < 9) || (blocksize_bits > PAGE_CACHE_SHIFT))
+               return -EINVAL;
+
+       if ((last_fs_block > (sector_t)(~0ULL) >> (blocksize_bits - 9)) ||
+           (last_fs_page > (pgoff_t)(~0ULL))) {
+               return -EFBIG;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(generic_check_addressable);
+
 /*
  * No-op implementation of ->fsync for in-memory filesystems.
  */
This page took 0.031329 seconds and 5 git commands to generate.