diff options
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/amigaffs.h | 1 | ||||
| -rw-r--r-- | include/linux/backing-dev.h | 30 | ||||
| -rw-r--r-- | include/linux/blk.h | 1 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 9 | ||||
| -rw-r--r-- | include/linux/buffer_head.h | 29 | ||||
| -rw-r--r-- | include/linux/dqblk_v1.h | 18 | ||||
| -rw-r--r-- | include/linux/dqblk_v2.h | 20 | ||||
| -rw-r--r-- | include/linux/fs.h | 122 | ||||
| -rw-r--r-- | include/linux/hfs_sysdep.h | 2 | ||||
| -rw-r--r-- | include/linux/jbd.h | 1 | ||||
| -rw-r--r-- | include/linux/locks.h | 28 | ||||
| -rw-r--r-- | include/linux/mm.h | 1 | ||||
| -rw-r--r-- | include/linux/module.h | 2 | ||||
| -rw-r--r-- | include/linux/nbd.h | 1 | ||||
| -rw-r--r-- | include/linux/nfs_fs.h | 2 | ||||
| -rw-r--r-- | include/linux/page-flags.h | 9 | ||||
| -rw-r--r-- | include/linux/quota.h | 255 | ||||
| -rw-r--r-- | include/linux/quotacompat.h | 86 | ||||
| -rw-r--r-- | include/linux/quotaio_v1.h | 33 | ||||
| -rw-r--r-- | include/linux/quotaio_v2.h | 79 | ||||
| -rw-r--r-- | include/linux/quotaops.h | 96 | ||||
| -rw-r--r-- | include/linux/raid/md.h | 1 | ||||
| -rw-r--r-- | include/linux/reiserfs_fs.h | 8 | ||||
| -rw-r--r-- | include/linux/swap.h | 1 | ||||
| -rw-r--r-- | include/linux/ufs_fs.h | 1 | ||||
| -rw-r--r-- | include/linux/writeback.h | 27 | ||||
| -rw-r--r-- | include/linux/xqm.h | 159 |
27 files changed, 793 insertions, 229 deletions
diff --git a/include/linux/amigaffs.h b/include/linux/amigaffs.h index 535c3bf41b9a..f02e8cbd0131 100644 --- a/include/linux/amigaffs.h +++ b/include/linux/amigaffs.h @@ -2,7 +2,6 @@ #define AMIGAFFS_H #include <linux/types.h> -#include <linux/locks.h> #include <asm/byteorder.h> diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h new file mode 100644 index 000000000000..075cacc389e1 --- /dev/null +++ b/include/linux/backing-dev.h @@ -0,0 +1,30 @@ +/* + * include/linux/backing-dev.h + * + * low-level device information and state which is propagated up through + * to high-level code. + */ + +#ifndef _LINUX_BACKING_DEV_H +#define _LINUX_BACKING_DEV_H + +/* + * Bits in backing_dev_info.state + */ +enum bdi_state { + BDI_pdflush, /* A pdflush thread is working this device */ + BDI_unused, /* Available bits start here */ +}; + +struct backing_dev_info { + unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */ + unsigned long state; /* Always use atomic bitops on this */ +}; + +extern struct backing_dev_info default_backing_dev_info; + +int writeback_acquire(struct backing_dev_info *bdi); +int writeback_in_progress(struct backing_dev_info *bdi); +void writeback_release(struct backing_dev_info *bdi); + +#endif /* _LINUX_BACKING_DEV_H */ diff --git a/include/linux/blk.h b/include/linux/blk.h index 9be0913f6069..62d37b2b4c17 100644 --- a/include/linux/blk.h +++ b/include/linux/blk.h @@ -3,7 +3,6 @@ #include <linux/blkdev.h> #include <linux/elevator.h> -#include <linux/locks.h> #include <linux/config.h> #include <linux/spinlock.h> #include <linux/compiler.h> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d8175ccc104c..ac373e6a2454 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -7,6 +7,7 @@ #include <linux/tqueue.h> #include <linux/list.h> #include <linux/pagemap.h> +#include <linux/backing-dev.h> #include <asm/scatterlist.h> @@ -162,11 +163,7 @@ struct request_queue make_request_fn *make_request_fn; prep_rq_fn *prep_rq_fn; - /* - * The VM-level readahead tunable for this device. In - * units of PAGE_CACHE_SIZE pages. - */ - unsigned long ra_pages; + struct backing_dev_info backing_dev_info; /* * The queue owner gets to use this for whatever they like. @@ -328,7 +325,7 @@ extern void blk_queue_hardsect_size(request_queue_t *q, unsigned short); extern void blk_queue_segment_boundary(request_queue_t *q, unsigned long); extern void blk_queue_assign_lock(request_queue_t *q, spinlock_t *); extern void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn); -extern unsigned long *blk_get_ra_pages(struct block_device *bdev); +extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *); extern void blk_dump_rq_flags(struct request *, char *); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 500a082b7bcc..5560b6ee5878 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -29,6 +29,7 @@ enum bh_state_bits { struct page; struct kiobuf; struct buffer_head; +struct address_space; typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate); /* @@ -44,13 +45,13 @@ struct buffer_head { struct page *b_page; /* the page this bh is mapped to */ sector_t b_blocknr; /* block number */ - unsigned short b_size; /* block size */ + u32 b_size; /* block size */ char *b_data; /* pointer to data block */ struct block_device *b_bdev; bh_end_io_t *b_end_io; /* I/O completion */ void *b_private; /* reserved for b_end_io */ - struct list_head b_inode_buffers; /* list of inode dirty buffers */ + struct list_head b_assoc_buffers; /* associated with another mapping */ }; @@ -145,12 +146,19 @@ int try_to_free_buffers(struct page *); void create_empty_buffers(struct page *, unsigned long, unsigned long b_state); void end_buffer_io_sync(struct buffer_head *bh, int uptodate); + +/* Things to do with buffers at mapping->private_list */ void buffer_insert_list(spinlock_t *lock, struct buffer_head *, struct list_head *); +void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode); +int write_mapping_buffers(struct address_space *mapping); +int inode_has_buffers(struct inode *); +void invalidate_inode_buffers(struct inode *); +int fsync_buffers_list(spinlock_t *lock, struct list_head *); +int sync_mapping_buffers(struct address_space *mapping); void mark_buffer_async_read(struct buffer_head *bh); void mark_buffer_async_write(struct buffer_head *bh); -void invalidate_inode_buffers(struct inode *); void invalidate_bdev(struct block_device *, int); void __invalidate_buffers(kdev_t dev, int); int sync_blockdev(struct block_device *bdev); @@ -161,8 +169,6 @@ int fsync_dev(kdev_t); int fsync_bdev(struct block_device *); int fsync_super(struct super_block *); int fsync_no_super(struct block_device *); -int fsync_buffers_list(spinlock_t *lock, struct list_head *); -int inode_has_buffers(struct inode *); struct buffer_head *__get_hash_table(struct block_device *, sector_t, int); struct buffer_head * __getblk(struct block_device *, sector_t, int); void __brelse(struct buffer_head *); @@ -217,14 +223,6 @@ static inline void put_bh(struct buffer_head *bh) atomic_dec(&bh->b_count); } -static inline void -mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode) -{ - mark_buffer_dirty(bh); - buffer_insert_list(&inode->i_bufferlist_lock, - bh, &inode->i_dirty_buffers); -} - /* * If an error happens during the make_request, this function * has to be recalled. It marks the buffer as clean and not @@ -243,11 +241,6 @@ static inline void buffer_IO_error(struct buffer_head * bh) bh->b_end_io(bh, buffer_uptodate(bh)); } -static inline int fsync_inode_buffers(struct inode *inode) -{ - return fsync_buffers_list(&inode->i_bufferlist_lock, - &inode->i_dirty_buffers); -} static inline void brelse(struct buffer_head *buf) { diff --git a/include/linux/dqblk_v1.h b/include/linux/dqblk_v1.h new file mode 100644 index 000000000000..42fbf4797156 --- /dev/null +++ b/include/linux/dqblk_v1.h @@ -0,0 +1,18 @@ +/* + * File with in-memory structures of old quota format + */ + +#ifndef _LINUX_DQBLK_V1_H +#define _LINUX_DQBLK_V1_H + +/* Id of quota format */ +#define QFMT_VFS_OLD 1 + +/* Root squash turned on */ +#define V1_DQF_RSQUASH 1 + +/* Special information about quotafile */ +struct v1_mem_dqinfo { +}; + +#endif /* _LINUX_DQBLK_V1_H */ diff --git a/include/linux/dqblk_v2.h b/include/linux/dqblk_v2.h new file mode 100644 index 000000000000..4a6c5f6867bb --- /dev/null +++ b/include/linux/dqblk_v2.h @@ -0,0 +1,20 @@ +/* + * Definitions of structures for vfsv0 quota format + */ + +#ifndef _LINUX_DQBLK_V2_H +#define _LINUX_DQBLK_V2_H + +#include <linux/types.h> + +/* id numbers of quota format */ +#define QFMT_VFS_V0 2 + +/* Inmemory copy of version specific information */ +struct v2_mem_dqinfo { + unsigned int dqi_blocks; + unsigned int dqi_free_blk; + unsigned int dqi_free_entry; +}; + +#endif /* _LINUX_DQBLK_V2_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 4b858f90c6fe..ab0a05dc8e26 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -112,7 +112,6 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #define MS_MOVE 8192 #define MS_REC 16384 #define MS_VERBOSE 32768 -#define MS_FLUSHING (1<<16) /* inodes are currently under writeout */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) @@ -156,7 +155,6 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY) #define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) || ((inode)->i_flags & S_SYNC)) #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) -#define IS_FLUSHING(inode) __IS_FLG(inode, MS_FLUSHING) #define IS_QUOTAINIT(inode) ((inode)->i_flags & S_QUOTA) #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) @@ -305,7 +303,9 @@ struct address_space_operations { int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int); }; +struct backing_dev_info; struct address_space { + struct inode *host; /* owner: inode, block_device */ struct radix_tree_root page_tree; /* radix tree of all pages */ rwlock_t page_lock; /* and rwlock protecting it */ struct list_head clean_pages; /* list of clean pages */ @@ -314,13 +314,15 @@ struct address_space { struct list_head io_pages; /* being prepared for I/O */ unsigned long nrpages; /* number of total pages */ struct address_space_operations *a_ops; /* methods */ - struct inode *host; /* owner: inode, block_device */ list_t i_mmap; /* list of private mappings */ list_t i_mmap_shared; /* list of private mappings */ spinlock_t i_shared_lock; /* and spinlock protecting it */ unsigned long dirtied_when; /* jiffies of first page dirtying */ int gfp_mask; /* how to allocate the pages */ - unsigned long *ra_pages; /* device readahead */ + struct backing_dev_info *backing_dev_info; /* device readahead, etc */ + spinlock_t private_lock; /* for use by the address_space */ + struct list_head private_list; /* ditto */ + struct address_space *assoc_mapping; /* ditto */ }; struct char_device { @@ -350,10 +352,6 @@ struct inode { struct list_head i_hash; struct list_head i_list; struct list_head i_dentry; - - struct list_head i_dirty_buffers; /* uses i_bufferlist_lock */ - spinlock_t i_bufferlist_lock; - unsigned long i_ino; atomic_t i_count; kdev_t i_dev; @@ -370,6 +368,7 @@ struct inode { unsigned long i_blksize; unsigned long i_blocks; unsigned long i_version; + unsigned short i_bytes; struct semaphore i_sem; struct inode_operations *i_op; struct file_operations *i_fop; /* former ->i_op->default_file_ops */ @@ -427,6 +426,39 @@ struct fown_struct { int signum; /* posix.1b rt signal to be delivered on IO */ }; +static inline void inode_add_bytes(struct inode *inode, loff_t bytes) +{ + inode->i_blocks += bytes >> 9; + bytes &= 511; + inode->i_bytes += bytes; + if (inode->i_bytes >= 512) { + inode->i_blocks++; + inode->i_bytes -= 512; + } +} + +static inline void inode_sub_bytes(struct inode *inode, loff_t bytes) +{ + inode->i_blocks -= bytes >> 9; + bytes &= 511; + if (inode->i_bytes < bytes) { + inode->i_blocks--; + inode->i_bytes += 512; + } + inode->i_bytes -= bytes; +} + +static inline loff_t inode_get_bytes(struct inode *inode) +{ + return (((loff_t)inode->i_blocks) << 9) + inode->i_bytes; +} + +static inline void inode_set_bytes(struct inode *inode, loff_t bytes) +{ + inode->i_blocks = bytes >> 9; + inode->i_bytes = bytes & 511; +} + /* * Track a single file's readahead state */ @@ -583,20 +615,6 @@ struct nameidata { struct vfsmount *old_mnt; }; -#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ -#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ - -struct quota_mount_options -{ - unsigned int flags; /* Flags for diskquotas on this device */ - struct semaphore dqio_sem; /* lock device while I/O in progress */ - struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */ - struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ - time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */ - time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */ - char rsquash[MAXQUOTAS]; /* for quotas threat root as any other user */ -}; - /* * Umount options */ @@ -620,13 +638,13 @@ struct super_block { kdev_t s_dev; unsigned long s_blocksize; unsigned long s_old_blocksize; - unsigned short s_writeback_gen;/* To avoid writeback livelock */ unsigned char s_blocksize_bits; unsigned char s_dirt; unsigned long long s_maxbytes; /* Max file size */ struct file_system_type *s_type; struct super_operations *s_op; struct dquot_operations *dq_op; + struct quotactl_ops *s_qcop; struct export_operations *s_export_op; unsigned long s_flags; unsigned long s_magic; @@ -634,16 +652,18 @@ struct super_block { struct rw_semaphore s_umount; struct semaphore s_lock; int s_count; + int s_syncing; atomic_t s_active; struct list_head s_dirty; /* dirty inodes */ + struct list_head s_io; /* parked for writeback */ struct list_head s_locked_inodes;/* inodes being synced */ struct list_head s_anon; /* anonymous dentries for (nfs) exporting */ struct list_head s_files; struct block_device *s_bdev; struct list_head s_instances; - struct quota_mount_options s_dquot; /* Diskquota specific options */ + struct quota_info s_dquot; /* Diskquota specific options */ char s_id[32]; /* Informational name */ @@ -663,6 +683,19 @@ struct super_block { }; /* + * Superblock locking. + */ +static inline void lock_super(struct super_block * sb) +{ + down(&sb->s_lock); +} + +static inline void unlock_super(struct super_block * sb) +{ + up(&sb->s_lock); +} + +/* * VFS helper functions.. */ extern int vfs_create(struct inode *, struct dentry *, int); @@ -772,13 +805,6 @@ struct super_operations { void (*read_inode) (struct inode *); - /* reiserfs kludge. reiserfs needs 64 bits of information to - ** find an inode. We are using the read_inode2 call to get - ** that information. We don't like this, and are waiting on some - ** VFS changes for the real solution. - ** iget4 calls read_inode2, iff it is defined - */ - void (*read_inode2) (struct inode *, void *) ; void (*dirty_inode) (struct inode *); void (*write_inode) (struct inode *, int); void (*put_inode) (struct inode *); @@ -802,6 +828,7 @@ struct super_operations { #define I_LOCK 8 #define I_FREEING 16 #define I_CLEAR 32 +#define I_NEW 64 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) @@ -816,16 +843,6 @@ static inline void mark_inode_dirty_sync(struct inode *inode) __mark_inode_dirty(inode, I_DIRTY_SYNC); } -struct dquot_operations { - void (*initialize) (struct inode *, short); - void (*drop) (struct inode *); - int (*alloc_block) (struct inode *, unsigned long, char); - int (*alloc_inode) (const struct inode *, unsigned long); - void (*free_block) (struct inode *, unsigned long); - void (*free_inode) (const struct inode *, unsigned long); - int (*transfer) (struct inode *, struct iattr *); -}; - /** * &export_operations - for nfsd to communicate with file systems @@ -1118,7 +1135,6 @@ extern int invalidate_device(kdev_t, int); extern void invalidate_inode_pages(struct inode *); extern void invalidate_inode_pages2(struct address_space *); extern void write_inode_now(struct inode *, int); -extern void sync_inodes_sb(struct super_block *); extern int filemap_fdatawrite(struct address_space *); extern int filemap_fdatawait(struct address_space *); extern void sync_supers(void); @@ -1210,19 +1226,33 @@ extern void force_delete(struct inode *); extern struct inode * igrab(struct inode *); extern ino_t iunique(struct super_block *, ino_t); -typedef int (*find_inode_t)(struct inode *, unsigned long, void *); -extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *); +extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); +extern struct inode * iget_locked(struct super_block *, unsigned long); +extern void unlock_new_inode(struct inode *); + static inline struct inode *iget(struct super_block *sb, unsigned long ino) { - return iget4(sb, ino, NULL, NULL); + struct inode *inode = iget_locked(sb, ino); + + if (inode && (inode->i_state & I_NEW)) { + sb->s_op->read_inode(inode); + unlock_new_inode(inode); + } + + return inode; } extern void __iget(struct inode * inode); extern void clear_inode(struct inode *); extern struct inode *new_inode(struct super_block *); extern void remove_suid(struct dentry *); -extern void insert_inode_hash(struct inode *); + +extern void __insert_inode_hash(struct inode *, unsigned long hashval); extern void remove_inode_hash(struct inode *); +static inline void insert_inode_hash(struct inode *inode) { + __insert_inode_hash(inode, inode->i_ino); +} + extern struct file * get_empty_filp(void); extern void file_move(struct file *f, struct list_head *list); extern void ll_rw_block(int, int, struct buffer_head * bh[]); diff --git a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h index 62fcf2ea311f..a08d5aa9e39d 100644 --- a/include/linux/hfs_sysdep.h +++ b/include/linux/hfs_sysdep.h @@ -19,8 +19,8 @@ #include <linux/slab.h> #include <linux/types.h> -#include <linux/locks.h> #include <linux/fs.h> +#include <linux/sched.h> #include <asm/byteorder.h> #include <asm/unaligned.h> diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 2752f3a7375d..4a96c4ac35b9 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -235,6 +235,7 @@ enum jbd_state_bits { BUFFER_FNS(JBD, jbd) BUFFER_FNS(JBDDirty, jbddirty) +TAS_BUFFER_FNS(JBDDirty, jbddirty) static inline struct buffer_head *jh2bh(struct journal_head *jh) { diff --git a/include/linux/locks.h b/include/linux/locks.h deleted file mode 100644 index a380c5e4f0bb..000000000000 --- a/include/linux/locks.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _LINUX_LOCKS_H -#define _LINUX_LOCKS_H - -#ifndef _LINUX_MM_H -#include <linux/mm.h> -#endif -#ifndef _LINUX_PAGEMAP_H -#include <linux/pagemap.h> -#endif - -/* - * super-block locking. Again, interrupts may only unlock - * a super-block (although even this isn't done right now. - * nfs may need it). - */ - -static inline void lock_super(struct super_block * sb) -{ - down(&sb->s_lock); -} - -static inline void unlock_super(struct super_block * sb) -{ - up(&sb->s_lock); -} - -#endif /* _LINUX_LOCKS_H */ - diff --git a/include/linux/mm.h b/include/linux/mm.h index 2f0b56f0183b..451cdff1ec16 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -454,7 +454,6 @@ void do_page_cache_readahead(struct file *file, void page_cache_readahead(struct file *file, unsigned long offset); void page_cache_readaround(struct file *file, unsigned long offset); void handle_ra_thrashing(struct file *file); -extern unsigned long default_ra_pages; /* vma is the first one with address < vma->vm_end, * and even address < vma->vm_start. Have to extend vma. */ diff --git a/include/linux/module.h b/include/linux/module.h index f3a8370db10a..1021d58d1742 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -370,6 +370,8 @@ extern struct module *module_list; #define EXPORT_SYMBOL_NOVERS(var) error this_object_must_be_defined_as_export_objs_in_the_Makefile #define EXPORT_SYMBOL_GPL(var) error this_object_must_be_defined_as_export_objs_in_the_Makefile +__asm__(".section __ksymtab,\"a\"\n.previous"); + #else #define __EXPORT_SYMBOL(sym, str) \ diff --git a/include/linux/nbd.h b/include/linux/nbd.h index b6120317731d..556b847804ca 100644 --- a/include/linux/nbd.h +++ b/include/linux/nbd.h @@ -22,7 +22,6 @@ #ifdef MAJOR_NR -#include <linux/locks.h> #include <asm/semaphore.h> #define LOCAL_END_REQUEST diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 499b246788f4..a8a2259a8343 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -170,7 +170,6 @@ struct nfs_inode { #define NFS_INO_REVALIDATING 0x0004 /* revalidating attrs */ #define NFS_IS_SNAPSHOT 0x0010 /* a snapshot file */ #define NFS_INO_FLUSH 0x0020 /* inode is due for flushing */ -#define NFS_INO_NEW 0x0040 /* hadn't been filled yet */ static inline struct nfs_inode *NFS_I(struct inode *inode) { @@ -208,7 +207,6 @@ do { \ #define NFS_FLAGS(inode) (NFS_I(inode)->flags) #define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATING) #define NFS_STALE(inode) (NFS_FLAGS(inode) & NFS_INO_STALE) -#define NFS_NEW(inode) (NFS_FLAGS(inode) & NFS_INO_NEW) #define NFS_FILEID(inode) (NFS_I(inode)->fileid) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index f56db65ebef3..52b7117c4f64 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -62,9 +62,8 @@ #define PG_arch_1 10 #define PG_reserved 11 -#define PG_launder 12 /* written out by VM pressure.. */ -#define PG_private 13 /* Has something at ->private */ -#define PG_writeback 14 /* Page is under writeback */ +#define PG_private 12 /* Has something at ->private */ +#define PG_writeback 13 /* Page is under writeback */ /* * Global page accounting. One instance per CPU. @@ -172,10 +171,6 @@ extern void get_page_state(struct page_state *ret); #define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags) #define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags) -#define PageLaunder(page) test_bit(PG_launder, &(page)->flags) -#define SetPageLaunder(page) set_bit(PG_launder, &(page)->flags) -#define ClearPageLaunder(page) clear_bit(PG_launder, &(page)->flags) - #define SetPagePrivate(page) set_bit(PG_private, &(page)->flags) #define ClearPagePrivate(page) clear_bit(PG_private, &(page)->flags) #define PagePrivate(page) test_bit(PG_private, &(page)->flags) diff --git a/include/linux/quota.h b/include/linux/quota.h index b2d5de7368f6..0a36a5e59caf 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -40,30 +40,22 @@ #define _LINUX_QUOTA_ #include <linux/errno.h> +#include <linux/types.h> -/* - * Convert diskblocks to blocks and the other way around. - */ -#define dbtob(num) (num << BLOCK_SIZE_BITS) -#define btodb(num) (num >> BLOCK_SIZE_BITS) +#define __DQUOT_VERSION__ "dquot_6.5.1" +#define __DQUOT_NUM_VERSION__ 6*10000+5*100+1 -/* - * Convert count of filesystem blocks to diskquota blocks, meant - * for filesystems where i_blksize != BLOCK_SIZE - */ -#define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE) +typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */ +typedef __u64 qsize_t; /* Type in which we store sizes */ -/* - * Definitions for disk quotas imposed on the average user - * (big brother finally hits Linux). - * - * The following constants define the amount of time given a user - * before the soft limits are treated as hard limits (usually resulting - * in an allocation failure). The timer is started when the user crosses - * their soft limit, it is reset when they go below their soft limit. - */ -#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ -#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ +/* Size of blocks in which are counted size limits */ +#define QUOTABLOCK_BITS 10 +#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS) + +/* Conversion routines from and to quota blocks */ +#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10)) +#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10)) +#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS) #define MAXQUOTAS 2 #define USRQUOTA 0 /* element used for user quotas */ @@ -78,9 +70,6 @@ "undefined", \ }; -#define QUOTAFILENAME "quota" -#define QUOTAGROUP "staff" - /* * Command definitions for the 'quotactl' system call. * The commands are broken into a main command defined below @@ -91,45 +80,111 @@ #define SUBCMDSHIFT 8 #define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) -#define Q_QUOTAON 0x0100 /* enable quotas */ -#define Q_QUOTAOFF 0x0200 /* disable quotas */ -#define Q_GETQUOTA 0x0300 /* get limits and usage */ -#define Q_SETQUOTA 0x0400 /* set limits and usage */ -#define Q_SETUSE 0x0500 /* set usage */ -#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ -#define Q_SETQLIM 0x0700 /* set limits */ -#define Q_GETSTATS 0x0800 /* get collected stats */ -#define Q_RSQUASH 0x1000 /* set root_squash option */ +#define Q_SYNC 0x800001 /* sync disk copy of a filesystems quotas */ +#define Q_QUOTAON 0x800002 /* turn quotas on */ +#define Q_QUOTAOFF 0x800003 /* turn quotas off */ +#define Q_GETFMT 0x800004 /* get quota format used on given filesystem */ +#define Q_GETINFO 0x800005 /* get information about quota files */ +#define Q_SETINFO 0x800006 /* set information about quota files */ +#define Q_GETQUOTA 0x800007 /* get user quota structure */ +#define Q_SETQUOTA 0x800008 /* set user quota structure */ + +/* + * Quota structure used for communication with userspace via quotactl + * Following flags are used to specify which fields are valid + */ +#define QIF_BLIMITS 1 +#define QIF_SPACE 2 +#define QIF_ILIMITS 4 +#define QIF_INODES 8 +#define QIF_BTIME 16 +#define QIF_ITIME 32 +#define QIF_LIMITS (QIF_BLIMITS | QIF_ILIMITS) +#define QIF_USAGE (QIF_SPACE | QIF_INODES) +#define QIF_TIMES (QIF_BTIME | QIF_ITIME) +#define QIF_ALL (QIF_LIMITS | QIF_USAGE | QIF_TIMES) + +struct if_dqblk { + __u64 dqb_bhardlimit; + __u64 dqb_bsoftlimit; + __u64 dqb_curspace; + __u64 dqb_ihardlimit; + __u64 dqb_isoftlimit; + __u64 dqb_curinodes; + __u64 dqb_btime; + __u64 dqb_itime; + __u32 dqb_valid; +}; /* - * The following structure defines the format of the disk quota file - * (as it appears on disk) - the file is an array of these structures - * indexed by user or group number. + * Structure used for setting quota information about file via quotactl + * Following flags are used to specify which fields are valid */ -struct dqblk { +#define IIF_BGRACE 1 +#define IIF_IGRACE 2 +#define IIF_FLAGS 4 +#define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS) + +struct if_dqinfo { + __u64 dqi_bgrace; + __u64 dqi_igrace; + __u32 dqi_flags; + __u32 dqi_valid; +}; + +#ifdef __KERNEL__ + +#include <linux/xqm.h> +#include <linux/dqblk_v1.h> +#include <linux/dqblk_v2.h> + +/* + * Data for one user/group kept in memory + */ +struct mem_dqblk { __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */ __u32 dqb_bsoftlimit; /* preferred limit on disk blks */ - __u32 dqb_curblocks; /* current block count */ + qsize_t dqb_curspace; /* current used space */ __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */ __u32 dqb_isoftlimit; /* preferred inode limit */ __u32 dqb_curinodes; /* current # allocated inodes */ - time_t dqb_btime; /* time limit for excessive disk use */ - time_t dqb_itime; /* time limit for excessive inode use */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive inode use */ }; /* - * Shorthand notation. + * Data for one quotafile kept in memory */ -#define dq_bhardlimit dq_dqb.dqb_bhardlimit -#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit -#define dq_curblocks dq_dqb.dqb_curblocks -#define dq_ihardlimit dq_dqb.dqb_ihardlimit -#define dq_isoftlimit dq_dqb.dqb_isoftlimit -#define dq_curinodes dq_dqb.dqb_curinodes -#define dq_btime dq_dqb.dqb_btime -#define dq_itime dq_dqb.dqb_itime +struct quota_format_type; + +struct mem_dqinfo { + struct quota_format_type *dqi_format; + int dqi_flags; + unsigned int dqi_bgrace; + unsigned int dqi_igrace; + union { + struct v1_mem_dqinfo v1_i; + struct v2_mem_dqinfo v2_i; + } u; +}; + +#define DQF_MASK 0xffff /* Mask for format specific flags */ +#define DQF_INFO_DIRTY 0x10000 /* Is info dirty? */ +#define DQF_ANY_DQUOT_DIRTY 0x20000 /* Is any dquot dirty? */ + +extern inline void mark_info_dirty(struct mem_dqinfo *info) +{ + info->dqi_flags |= DQF_INFO_DIRTY; +} -#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) +#define info_dirty(info) ((info)->dqi_flags & DQF_INFO_DIRTY) + +#define info_any_dirty(info) ((info)->dqi_flags & DQF_INFO_DIRTY ||\ + (info)->dqi_flags & DQF_ANY_DQUOT_DIRTY) + +#define sb_dqopt(sb) (&(sb)->s_dquot) + +extern int nr_dquots, nr_free_dquots; struct dqstats { __u32 lookups; @@ -142,9 +197,7 @@ struct dqstats { __u32 syncs; }; -#ifdef __KERNEL__ - -extern int dquot_root_squash; +extern struct dqstats dqstats; #define NR_DQHASH 43 /* Just an arbitrary number */ @@ -161,36 +214,112 @@ struct dquot { struct list_head dq_free; /* Free list element */ wait_queue_head_t dq_wait_lock; /* Pointer to waitqueue on dquot lock */ wait_queue_head_t dq_wait_free; /* Pointer to waitqueue for quota to be unused */ - int dq_count; /* Reference count */ + int dq_count; /* Use count */ + int dq_dup_ref; /* Number of duplicated refences */ /* fields after this point are cleared when invalidating */ struct super_block *dq_sb; /* superblock this applies to */ unsigned int dq_id; /* ID this applies to (uid, gid) */ + loff_t dq_off; /* Offset of dquot on disk */ short dq_type; /* Type of quota */ short dq_flags; /* See DQ_* */ unsigned long dq_referenced; /* Number of times this dquot was referenced during its lifetime */ - struct dqblk dq_dqb; /* Diskquota usage */ + struct mem_dqblk dq_dqb; /* Diskquota usage */ }; #define NODQUOT (struct dquot *)NULL -/* - * Flags used for set_dqblk. - */ -#define SET_QUOTA 0x02 -#define SET_USE 0x04 -#define SET_QLIMIT 0x08 - #define QUOTA_OK 0 #define NO_QUOTA 1 +/* Operations which must be implemented by each quota format */ +struct quota_format_ops { + int (*check_quota_file)(struct super_block *sb, int type); /* Detect whether file is in our format */ + int (*read_file_info)(struct super_block *sb, int type); /* Read main info about file - called on quotaon() */ + int (*write_file_info)(struct super_block *sb, int type); /* Write main info about file */ + int (*free_file_info)(struct super_block *sb, int type); /* Called on quotaoff() */ + int (*read_dqblk)(struct dquot *dquot); /* Read structure for one user */ + int (*commit_dqblk)(struct dquot *dquot); /* Write (or delete) structure for one user */ +}; + +/* Operations working with dquots */ +struct dquot_operations { + void (*initialize) (struct inode *, int); + void (*drop) (struct inode *); + int (*alloc_space) (struct inode *, qsize_t, int); + int (*alloc_inode) (const struct inode *, unsigned long); + void (*free_space) (struct inode *, qsize_t); + void (*free_inode) (const struct inode *, unsigned long); + int (*transfer) (struct inode *, struct iattr *); +}; + +/* Operations handling requests from userspace */ +struct quotactl_ops { + int (*quota_on)(struct super_block *, int, int, char *); + int (*quota_off)(struct super_block *, int); + int (*quota_sync)(struct super_block *, int); + int (*get_info)(struct super_block *, int, struct if_dqinfo *); + int (*set_info)(struct super_block *, int, struct if_dqinfo *); + int (*get_dqblk)(struct super_block *, int, qid_t, struct if_dqblk *); + int (*set_dqblk)(struct super_block *, int, qid_t, struct if_dqblk *); + int (*get_xstate)(struct super_block *, struct fs_quota_stat *); + int (*set_xstate)(struct super_block *, unsigned int, int); + int (*get_xquota)(struct super_block *, int, qid_t, struct fs_disk_quota *); + int (*set_xquota)(struct super_block *, int, qid_t, struct fs_disk_quota *); +}; + +struct quota_format_type { + int qf_fmt_id; /* Quota format id */ + struct quota_format_ops *qf_ops; /* Operations of format */ + struct module *qf_owner; /* Module implementing quota format */ + struct quota_format_type *qf_next; +}; + +#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ +#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ + +struct quota_info { + unsigned int flags; /* Flags for diskquotas on this device */ + struct semaphore dqio_sem; /* lock device while I/O in progress */ + struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */ + struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ + struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ + struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ +}; + +/* Inline would be better but we need to dereference super_block which is not defined yet */ +#define mark_dquot_dirty(dquot) do {\ + dquot->dq_flags |= DQ_MOD;\ + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_flags |= DQF_ANY_DQUOT_DIRTY;\ +} while (0) + +#define dquot_dirty(dquot) ((dquot)->dq_flags & DQ_MOD) + +static inline int is_enabled(struct quota_info *dqopt, int type) +{ + switch (type) { + case USRQUOTA: + return dqopt->flags & DQUOT_USR_ENABLED; + case GRPQUOTA: + return dqopt->flags & DQUOT_GRP_ENABLED; + } + return 0; +} + +#define sb_any_quota_enabled(sb) (is_enabled(sb_dqopt(sb), USRQUOTA) | is_enabled(sb_dqopt(sb), GRPQUOTA)) + +#define sb_has_quota_enabled(sb, type) (is_enabled(sb_dqopt(sb), type)) + +int register_quota_format(struct quota_format_type *fmt); +void unregister_quota_format(struct quota_format_type *fmt); + #else # /* nodep */ include <sys/cdefs.h> __BEGIN_DECLS -long quotactl __P ((int, const char *, int, caddr_t)); +long quotactl __P ((unsigned int, const char *, int, caddr_t)); __END_DECLS #endif /* __KERNEL__ */ diff --git a/include/linux/quotacompat.h b/include/linux/quotacompat.h new file mode 100644 index 000000000000..484aac17efc9 --- /dev/null +++ b/include/linux/quotacompat.h @@ -0,0 +1,86 @@ +/* + * Definition of symbols used for backward compatible interface + */ + +#ifndef _LINUX_QUOTACOMPAT_ +#define _LINUX_QUOTACOMPAT_ + +#include <linux/types.h> +#include <linux/quota.h> + +struct v1c_mem_dqblk { + __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */ + __u32 dqb_bsoftlimit; /* preferred limit on disk blks */ + __u32 dqb_curblocks; /* current block count */ + __u32 dqb_ihardlimit; /* maximum # allocated inodes */ + __u32 dqb_isoftlimit; /* preferred inode limit */ + __u32 dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive files */ +}; + +struct v1c_dqstats { + __u32 lookups; + __u32 drops; + __u32 reads; + __u32 writes; + __u32 cache_hits; + __u32 allocated_dquots; + __u32 free_dquots; + __u32 syncs; +}; + +struct v2c_mem_dqblk { + unsigned int dqb_ihardlimit; + unsigned int dqb_isoftlimit; + unsigned int dqb_curinodes; + unsigned int dqb_bhardlimit; + unsigned int dqb_bsoftlimit; + qsize_t dqb_curspace; + __kernel_time_t dqb_btime; + __kernel_time_t dqb_itime; +}; + +struct v2c_mem_dqinfo { + unsigned int dqi_bgrace; + unsigned int dqi_igrace; + unsigned int dqi_flags; + unsigned int dqi_blocks; + unsigned int dqi_free_blk; + unsigned int dqi_free_entry; +}; + +struct v2c_dqstats { + __u32 lookups; + __u32 drops; + __u32 reads; + __u32 writes; + __u32 cache_hits; + __u32 allocated_dquots; + __u32 free_dquots; + __u32 syncs; + __u32 version; +}; + +#define Q_COMP_QUOTAON 0x0100 /* enable quotas */ +#define Q_COMP_QUOTAOFF 0x0200 /* disable quotas */ +#define Q_COMP_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ + +#define Q_V1_GETQUOTA 0x0300 /* get limits and usage */ +#define Q_V1_SETQUOTA 0x0400 /* set limits and usage */ +#define Q_V1_SETUSE 0x0500 /* set usage */ +#define Q_V1_SETQLIM 0x0700 /* set limits */ +#define Q_V1_GETSTATS 0x0800 /* get collected stats */ +#define Q_V1_RSQUASH 0x1000 /* set root_squash option */ + +#define Q_V2_SETQLIM 0x0700 /* set limits */ +#define Q_V2_GETINFO 0x0900 /* get info about quotas - graces, flags... */ +#define Q_V2_SETINFO 0x0A00 /* set info about quotas */ +#define Q_V2_SETGRACE 0x0B00 /* set inode and block grace */ +#define Q_V2_SETFLAGS 0x0C00 /* set flags for quota */ +#define Q_V2_GETQUOTA 0x0D00 /* get limits and usage */ +#define Q_V2_SETQUOTA 0x0E00 /* set limits and usage */ +#define Q_V2_SETUSE 0x0F00 /* set usage */ +#define Q_V2_GETSTATS 0x1100 /* get collected stats */ + +#endif diff --git a/include/linux/quotaio_v1.h b/include/linux/quotaio_v1.h new file mode 100644 index 000000000000..746654b5de70 --- /dev/null +++ b/include/linux/quotaio_v1.h @@ -0,0 +1,33 @@ +#ifndef _LINUX_QUOTAIO_V1_H +#define _LINUX_QUOTAIO_V1_H + +#include <linux/types.h> + +/* + * The following constants define the amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). The timer is started when the user crosses + * their soft limit, it is reset when they go below their soft limit. + */ +#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ +#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ + +/* + * The following structure defines the format of the disk quota file + * (as it appears on disk) - the file is an array of these structures + * indexed by user or group number. + */ +struct v1_disk_dqblk { + __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */ + __u32 dqb_bsoftlimit; /* preferred limit on disk blks */ + __u32 dqb_curblocks; /* current block count */ + __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */ + __u32 dqb_isoftlimit; /* preferred inode limit */ + __u32 dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive inode use */ +}; + +#define v1_dqoff(UID) ((loff_t)((UID) * sizeof (struct v1_disk_dqblk))) + +#endif /* _LINUX_QUOTAIO_V1_H */ diff --git a/include/linux/quotaio_v2.h b/include/linux/quotaio_v2.h new file mode 100644 index 000000000000..da4e02730bc8 --- /dev/null +++ b/include/linux/quotaio_v2.h @@ -0,0 +1,79 @@ +/* + * Definitions of structures for vfsv0 quota format + */ + +#ifndef _LINUX_QUOTAIO_V2_H +#define _LINUX_QUOTAIO_V2_H + +#include <linux/types.h> +#include <linux/quota.h> + +/* + * Definitions of magics and versions of current quota files + */ +#define V2_INITQMAGICS {\ + 0xd9c01f11, /* USRQUOTA */\ + 0xd9c01927 /* GRPQUOTA */\ +} + +#define V2_INITQVERSIONS {\ + 0, /* USRQUOTA */\ + 0 /* GRPQUOTA */\ +} + +/* + * The following structure defines the format of the disk quota file + * (as it appears on disk) - the file is a radix tree whose leaves point + * to blocks of these structures. + */ +struct v2_disk_dqblk { + __u32 dqb_id; /* id this quota applies to */ + __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */ + __u32 dqb_isoftlimit; /* preferred inode limit */ + __u32 dqb_curinodes; /* current # allocated inodes */ + __u32 dqb_bhardlimit; /* absolute limit on disk space (in QUOTABLOCK_SIZE) */ + __u32 dqb_bsoftlimit; /* preferred limit on disk space (in QUOTABLOCK_SIZE) */ + __u64 dqb_curspace; /* current space occupied (in bytes) */ + __u64 dqb_btime; /* time limit for excessive disk use */ + __u64 dqb_itime; /* time limit for excessive inode use */ +}; + +/* + * Here are header structures as written on disk and their in-memory copies + */ +/* First generic header */ +struct v2_disk_dqheader { + __u32 dqh_magic; /* Magic number identifying file */ + __u32 dqh_version; /* File version */ +}; + +/* Header with type and version specific information */ +struct v2_disk_dqinfo { + __u32 dqi_bgrace; /* Time before block soft limit becomes hard limit */ + __u32 dqi_igrace; /* Time before inode soft limit becomes hard limit */ + __u32 dqi_flags; /* Flags for quotafile (DQF_*) */ + __u32 dqi_blocks; /* Number of blocks in file */ + __u32 dqi_free_blk; /* Number of first free block in the list */ + __u32 dqi_free_entry; /* Number of block with at least one free entry */ +}; + +/* + * Structure of header of block with quota structures. It is padded to 16 bytes so + * there will be space for exactly 18 quota-entries in a block + */ +struct v2_disk_dqdbheader { + __u32 dqdh_next_free; /* Number of next block with free entry */ + __u32 dqdh_prev_free; /* Number of previous block with free entry */ + __u16 dqdh_entries; /* Number of valid entries in block */ + __u16 dqdh_pad1; + __u32 dqdh_pad2; +}; + +#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader) /* Offset of info header in file */ +#define V2_DQBLKSIZE_BITS 10 +#define V2_DQBLKSIZE (1 << V2_DQBLKSIZE_BITS) /* Size of block with quota structures */ +#define V2_DQTREEOFF 1 /* Offset of tree in file in blocks */ +#define V2_DQTREEDEPTH 4 /* Depth of quota tree */ +#define V2_DQSTRINBLK ((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk)) /* Number of entries in one blocks */ + +#endif /* _LINUX_QUOTAIO_V2_H */ diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 0a1df9e1fe56..31b24e37c159 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -20,15 +20,15 @@ /* * declaration of quota_function calls in kernel. */ -extern void dquot_initialize(struct inode *inode, short type); +extern void sync_dquots(struct super_block *sb, int type); + +extern void dquot_initialize(struct inode *inode, int type); extern void dquot_drop(struct inode *inode); -extern int quota_off(struct super_block *sb, short type); -extern int sync_dquots(struct super_block *sb, short type); -extern int dquot_alloc_block(struct inode *inode, unsigned long number, char prealloc); +extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); extern int dquot_alloc_inode(const struct inode *inode, unsigned long number); -extern void dquot_free_block(struct inode *inode, unsigned long number); +extern void dquot_free_space(struct inode *inode, qsize_t number); extern void dquot_free_inode(const struct inode *inode, unsigned long number); extern int dquot_transfer(struct inode *inode, struct iattr *iattr); @@ -36,7 +36,11 @@ extern int dquot_transfer(struct inode *inode, struct iattr *iattr); /* * Operations supported for diskquotas. */ -#define sb_any_quota_enabled(sb) ((sb)->s_dquot.flags & (DQUOT_USR_ENABLED | DQUOT_GRP_ENABLED)) +extern struct dquot_operations dquot_operations; +extern struct quotactl_ops vfs_quotactl_ops; + +#define sb_dquot_ops (&dquot_operations) +#define sb_quotactl_ops (&vfs_quotactl_ops) static __inline__ void DQUOT_INIT(struct inode *inode) { @@ -59,50 +63,50 @@ static __inline__ void DQUOT_DROP(struct inode *inode) unlock_kernel(); } -static __inline__ int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, int nr) +static __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); if (sb_any_quota_enabled(inode->i_sb)) { - /* Number of used blocks is updated in alloc_block() */ - if (inode->i_sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, inode->i_sb->s_blocksize), 1) == NO_QUOTA) { + /* Used space is updated in alloc_space() */ + if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA) { unlock_kernel(); return 1; } } else - inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9); + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } -static __inline__ int DQUOT_PREALLOC_BLOCK(struct inode *inode, int nr) +static __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) { int ret; - if (!(ret = DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr))) + if (!(ret = DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr))) mark_inode_dirty(inode); return ret; } -static __inline__ int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, int nr) +static __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); if (sb_any_quota_enabled(inode->i_sb)) { - /* Number of used blocks is updated in alloc_block() */ - if (inode->i_sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, inode->i_sb->s_blocksize), 0) == NO_QUOTA) { + /* Used space is updated in alloc_space() */ + if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA) { unlock_kernel(); return 1; } } else - inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9); + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } -static __inline__ int DQUOT_ALLOC_BLOCK(struct inode *inode, int nr) +static __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) { int ret; - if (!(ret = DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr))) + if (!(ret = DQUOT_ALLOC_SPACE_NODIRTY(inode, nr))) mark_inode_dirty(inode); return ret; } @@ -121,19 +125,19 @@ static __inline__ int DQUOT_ALLOC_INODE(struct inode *inode) return 0; } -static __inline__ void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, int nr) +static __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); if (sb_any_quota_enabled(inode->i_sb)) - inode->i_sb->dq_op->free_block(inode, fs_to_dq_blocks(nr, inode->i_sb->s_blocksize)); + inode->i_sb->dq_op->free_space(inode, nr); else - inode->i_blocks -= nr << (inode->i_sb->s_blocksize_bits - 9); + inode_sub_bytes(inode, nr); unlock_kernel(); } -static __inline__ void DQUOT_FREE_BLOCK(struct inode *inode, int nr) +static __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) { - DQUOT_FREE_BLOCK_NODIRTY(inode, nr); + DQUOT_FREE_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); } @@ -160,13 +164,25 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr) } #define DQUOT_SYNC(sb) sync_dquots(sb, -1) -#define DQUOT_OFF(sb) quota_off(sb, -1) + +static __inline__ int DQUOT_OFF(struct super_block *sb) +{ + int ret = -ENOSYS; + + lock_kernel(); + if (sb->s_qcop && sb->s_qcop->quota_off) + ret = sb->s_qcop->quota_off(sb, -1); + unlock_kernel(); + return ret; +} #else /* * NO-OP when quota not configured. */ +#define sb_dquot_ops (NULL) +#define sb_quotactl_ops (NULL) #define DQUOT_INIT(inode) do { } while(0) #define DQUOT_DROP(inode) do { } while(0) #define DQUOT_ALLOC_INODE(inode) (0) @@ -174,48 +190,56 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr) #define DQUOT_SYNC(sb) do { } while(0) #define DQUOT_OFF(sb) do { } while(0) #define DQUOT_TRANSFER(inode, iattr) (0) -extern __inline__ int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, int nr) +extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); - inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9); + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } -extern __inline__ int DQUOT_PREALLOC_BLOCK(struct inode *inode, int nr) +extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) { - DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr); + DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, int nr) +extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); - inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9); + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } -extern __inline__ int DQUOT_ALLOC_BLOCK(struct inode *inode, int nr) +extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) { - DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr); + DQUOT_ALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, int nr) +extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); - inode->i_blocks -= nr << (inode->i_sb->s_blocksize_bits - 9); + inode_sub_bytes(inode, nr); unlock_kernel(); } -extern __inline__ void DQUOT_FREE_BLOCK(struct inode *inode, int nr) +extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) { - DQUOT_FREE_BLOCK_NODIRTY(inode, nr); + DQUOT_FREE_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); } #endif /* CONFIG_QUOTA */ + +#define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_PREALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) +#define DQUOT_PREALLOC_BLOCK(inode, nr) DQUOT_PREALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) +#define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_ALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) +#define DQUOT_ALLOC_BLOCK(inode, nr) DQUOT_ALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) +#define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) DQUOT_FREE_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) +#define DQUOT_FREE_BLOCK(inode, nr) DQUOT_FREE_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) + #endif /* _LINUX_QUOTAOPS_ */ diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index bf586df47298..cb6332482af2 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -31,7 +31,6 @@ #include <linux/delay.h> #include <net/checksum.h> #include <linux/random.h> -#include <linux/locks.h> #include <linux/kernel_stat.h> #include <asm/io.h> #include <linux/completion.h> diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index e98ccaf9d217..173279f6ff0a 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1564,8 +1564,9 @@ extern struct item_operations * item_ops [TYPE_ANY + 1]; #define B_I_POS_UNFM_POINTER(bh,ih,pos) le32_to_cpu(*(((unp_t *)B_I_PITEM(bh,ih)) + (pos))) #define PUT_B_I_POS_UNFM_POINTER(bh,ih,pos, val) do {*(((unp_t *)B_I_PITEM(bh,ih)) + (pos)) = cpu_to_le32(val); } while (0) -struct reiserfs_iget4_args { +struct reiserfs_iget_args { __u32 objectid ; + __u32 dirid ; } ; /***************************************************************************/ @@ -1818,8 +1819,9 @@ void padd_item (char * item, int total_length, int length); /* inode.c */ -void reiserfs_read_inode (struct inode * inode) ; -void reiserfs_read_inode2(struct inode * inode, void *p) ; +void reiserfs_read_locked_inode(struct inode * inode, struct reiserfs_iget_args *args) ; +int reiserfs_find_actor(struct inode * inode, void *p) ; +int reiserfs_init_locked_inode(struct inode * inode, void *p) ; void reiserfs_delete_inode (struct inode * inode); void reiserfs_write_inode (struct inode * inode, int) ; struct dentry *reiserfs_get_dentry(struct super_block *, void *) ; diff --git a/include/linux/swap.h b/include/linux/swap.h index 1674b5acd6f7..3a376842c21c 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -91,6 +91,7 @@ struct swap_info_struct { int next; /* next entry on swap list */ }; +struct inode; extern int nr_swap_pages; /* Swap 50% full? Release swapcache more aggressively.. */ diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index 609d0dab2c6f..faccf5ad22d5 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -31,6 +31,7 @@ #include <linux/kernel.h> #include <linux/time.h> #include <linux/stat.h> +#include <linux/fs.h> #define UFS_BBLOCK 0 #define UFS_BBSIZE 8192 diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 1978e06d1131..9dc03210ee62 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -13,20 +13,27 @@ extern struct list_head inode_in_use; extern struct list_head inode_unused; /* + * Yes, writeback.h requires sched.h + * No, sched.h is not included from here. + */ +static inline int current_is_pdflush(void) +{ + return current->flags & PF_FLUSHER; +} + +/* * fs/fs-writeback.c */ #define WB_SYNC_NONE 0 /* Don't wait on anything */ #define WB_SYNC_LAST 1 /* Wait on the last-written mapping */ #define WB_SYNC_ALL 2 /* Wait on every mapping */ +#define WB_SYNC_HOLD 3 /* Hold the inode on sb_dirty for sys_sync() */ -void try_to_writeback_unused_inodes(unsigned long pexclusive); -void writeback_single_inode(struct inode *inode, - int sync, int *nr_to_write); void writeback_unlocked_inodes(int *nr_to_write, int sync_mode, unsigned long *older_than_this); -void writeback_inodes_sb(struct super_block *); void __wait_on_inode(struct inode * inode); -void sync_inodes(void); +void sync_inodes_sb(struct super_block *, int wait); +void sync_inodes(int wait); static inline void wait_on_inode(struct inode *inode) { @@ -37,17 +44,9 @@ static inline void wait_on_inode(struct inode *inode) /* * mm/page-writeback.c */ -/* - * How much data to write out at a time in various places. This isn't - * really very important - it's just here to prevent any thread from - * locking an inode for too long and blocking other threads which wish - * to write the same file for allocation throttling purposes. - */ -#define WRITEOUT_PAGES ((4096 * 1024) / PAGE_CACHE_SIZE) - void balance_dirty_pages(struct address_space *mapping); void balance_dirty_pages_ratelimited(struct address_space *mapping); -int pdflush_flush(unsigned long nr_pages); int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); +int writeback_mapping(struct address_space *mapping, int *nr_to_write); #endif /* WRITEBACK_H */ diff --git a/include/linux/xqm.h b/include/linux/xqm.h new file mode 100644 index 000000000000..d077bc18a424 --- /dev/null +++ b/include/linux/xqm.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + * USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef _LINUX_XQM_H +#define _LINUX_XQM_H + +#include <linux/types.h> + +/* + * Disk quota - quotactl(2) commands for the XFS Quota Manager (XQM). + */ + +#define XQM_CMD(x) (('X'<<8)+(x)) /* note: forms first QCMD argument */ +#define Q_XQUOTAON XQM_CMD(0x1) /* enable accounting/enforcement */ +#define Q_XQUOTAOFF XQM_CMD(0x2) /* disable accounting/enforcement */ +#define Q_XGETQUOTA XQM_CMD(0x3) /* get disk limits and usage */ +#define Q_XSETQLIM XQM_CMD(0x4) /* set disk limits */ +#define Q_XGETQSTAT XQM_CMD(0x5) /* get quota subsystem status */ +#define Q_XQUOTARM XQM_CMD(0x6) /* free disk space used by dquots */ + +/* + * fs_disk_quota structure: + * + * This contains the current quota information regarding a user/proj/group. + * It is 64-bit aligned, and all the blk units are in BBs (Basic Blocks) of + * 512 bytes. + */ +#define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */ +typedef struct fs_disk_quota { + __s8 d_version; /* version of this structure */ + __s8 d_flags; /* XFS_{USER,PROJ,GROUP}_QUOTA */ + __u16 d_fieldmask; /* field specifier */ + __u32 d_id; /* user, project, or group ID */ + __u64 d_blk_hardlimit;/* absolute limit on disk blks */ + __u64 d_blk_softlimit;/* preferred limit on disk blks */ + __u64 d_ino_hardlimit;/* maximum # allocated inodes */ + __u64 d_ino_softlimit;/* preferred inode limit */ + __u64 d_bcount; /* # disk blocks owned by the user */ + __u64 d_icount; /* # inodes owned by the user */ + __s32 d_itimer; /* zero if within inode limits */ + /* if not, we refuse service */ + __s32 d_btimer; /* similar to above; for disk blocks */ + __u16 d_iwarns; /* # warnings issued wrt num inodes */ + __u16 d_bwarns; /* # warnings issued wrt disk blocks */ + __s32 d_padding2; /* padding2 - for future use */ + __u64 d_rtb_hardlimit;/* absolute limit on realtime blks */ + __u64 d_rtb_softlimit;/* preferred limit on RT disk blks */ + __u64 d_rtbcount; /* # realtime blocks owned */ + __s32 d_rtbtimer; /* similar to above; for RT disk blks */ + __u16 d_rtbwarns; /* # warnings issued wrt RT disk blks */ + __s16 d_padding3; /* padding3 - for future use */ + char d_padding4[8]; /* yet more padding */ +} fs_disk_quota_t; + +/* + * These fields are sent to Q_XSETQLIM to specify fields that need to change. + */ +#define FS_DQ_ISOFT (1<<0) +#define FS_DQ_IHARD (1<<1) +#define FS_DQ_BSOFT (1<<2) +#define FS_DQ_BHARD (1<<3) +#define FS_DQ_RTBSOFT (1<<4) +#define FS_DQ_RTBHARD (1<<5) +#define FS_DQ_LIMIT_MASK (FS_DQ_ISOFT | FS_DQ_IHARD | FS_DQ_BSOFT | \ + FS_DQ_BHARD | FS_DQ_RTBSOFT | FS_DQ_RTBHARD) +/* + * These timers can only be set in super user's dquot. For others, timers are + * automatically started and stopped. Superusers timer values set the limits + * for the rest. In case these values are zero, the DQ_{F,B}TIMELIMIT values + * defined below are used. + * These values also apply only to the d_fieldmask field for Q_XSETQLIM. + */ +#define FS_DQ_BTIMER (1<<6) +#define FS_DQ_ITIMER (1<<7) +#define FS_DQ_RTBTIMER (1<<8) +#define FS_DQ_TIMER_MASK (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER) + +/* + * The following constants define the default amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). These may be modified by the quotactl(2) + * system call with the Q_XSETQLIM command. + */ +#define DQ_FTIMELIMIT (7 * 24*60*60) /* 1 week */ +#define DQ_BTIMELIMIT (7 * 24*60*60) /* 1 week */ + +/* + * Various flags related to quotactl(2). Only relevant to XFS filesystems. + */ +#define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */ +#define XFS_QUOTA_UDQ_ENFD (1<<1) /* user quota limits enforcement */ +#define XFS_QUOTA_GDQ_ACCT (1<<2) /* group quota accounting */ +#define XFS_QUOTA_GDQ_ENFD (1<<3) /* group quota limits enforcement */ + +#define XFS_USER_QUOTA (1<<0) /* user quota type */ +#define XFS_PROJ_QUOTA (1<<1) /* (IRIX) project quota type */ +#define XFS_GROUP_QUOTA (1<<2) /* group quota type */ + +/* + * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system. + * Provides a centralized way to get meta infomation about the quota subsystem. + * eg. space taken up for user and group quotas, number of dquots currently + * incore. + */ +#define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */ + +/* + * Some basic infomation about 'quota files'. + */ +typedef struct fs_qfilestat { + __u64 qfs_ino; /* inode number */ + __u64 qfs_nblks; /* number of BBs 512-byte-blks */ + __u32 qfs_nextents; /* number of extents */ +} fs_qfilestat_t; + +typedef struct fs_quota_stat { + __s8 qs_version; /* version number for future changes */ + __u16 qs_flags; /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */ + __s8 qs_pad; /* unused */ + fs_qfilestat_t qs_uquota; /* user quota storage information */ + fs_qfilestat_t qs_gquota; /* group quota storage information */ + __u32 qs_incoredqs; /* number of dquots incore */ + __s32 qs_btimelimit; /* limit for blks timer */ + __s32 qs_itimelimit; /* limit for inodes timer */ + __s32 qs_rtbtimelimit;/* limit for rt blks timer */ + __u16 qs_bwarnlimit; /* limit for num warnings */ + __u16 qs_iwarnlimit; /* limit for num warnings */ +} fs_quota_stat_t; + +#endif /* _LINUX_XQM_H */ |
