Commit d9c0ffee authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.128

parent c2ef85f5
...@@ -1136,7 +1136,7 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, ...@@ -1136,7 +1136,7 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
unsigned long timeout; unsigned long timeout;
int ret; int ret;
timeout = ~0UL; timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) { if (tvp) {
time_t sec, usec; time_t sec, usec;
...@@ -1147,8 +1147,6 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, ...@@ -1147,8 +1147,6 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
timeout += sec * HZ; timeout += sec * HZ;
if (timeout)
timeout += jiffies + 1;
} }
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1168,7 +1166,7 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, ...@@ -1168,7 +1166,7 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
zero_fd_set(n, fds->res_out); zero_fd_set(n, fds->res_out);
zero_fd_set(n, fds->res_ex); zero_fd_set(n, fds->res_ex);
ret = do_select(n, fds, timeout); ret = do_select(n, fds, &timeout);
/* OSF does not copy back the remaining time. */ /* OSF does not copy back the remaining time. */
......
...@@ -331,11 +331,17 @@ void add_request(struct blk_dev_struct * dev, struct request * req) ...@@ -331,11 +331,17 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
goto out; goto out;
} }
for ( ; tmp->next ; tmp = tmp->next) { for ( ; tmp->next ; tmp = tmp->next) {
if ((IN_ORDER(tmp,req) || const int after_current = IN_ORDER(tmp,req);
!IN_ORDER(tmp,tmp->next)) && const int before_next = IN_ORDER(req,tmp->next);
IN_ORDER(req,tmp->next))
if (!IN_ORDER(tmp,tmp->next)) {
if (after_current || before_next)
break;
} else {
if (after_current && before_next)
break; break;
} }
}
req->next = tmp->next; req->next = tmp->next;
tmp->next = req; tmp->next = req;
......
...@@ -445,9 +445,9 @@ static int exec_mmap(void) ...@@ -445,9 +445,9 @@ static int exec_mmap(void)
/* /*
* This function makes sure the current process has its own signal table, * This function makes sure the current process has its own signal table,
* so that flush_old_signals can later reset the signals without disturbing * so that flush_signal_handlers can later reset the handlers without
* other processes. (Other processes might share the signal table via * disturbing other processes. (Other processes might share the signal
* the CLONE_SIGHAND option to clone().) * table via the CLONE_SIGHAND option to clone().)
*/ */
static inline int make_private_signals(void) static inline int make_private_signals(void)
...@@ -485,13 +485,6 @@ static inline void release_old_signals(struct signal_struct * oldsig) ...@@ -485,13 +485,6 @@ static inline void release_old_signals(struct signal_struct * oldsig)
* These functions flushes out all traces of the currently running executable * These functions flushes out all traces of the currently running executable
* so that a new one can be started * so that a new one can be started
*/ */
static inline void flush_old_signals(struct task_struct *t)
{
#if 0
flush_signals(t);
#endif
flush_signal_handlers(t);
}
static inline void flush_old_files(struct files_struct * files) static inline void flush_old_files(struct files_struct * files)
{ {
...@@ -554,7 +547,7 @@ int flush_old_exec(struct linux_binprm * bprm) ...@@ -554,7 +547,7 @@ int flush_old_exec(struct linux_binprm * bprm)
permission(bprm->dentry->d_inode,MAY_READ)) permission(bprm->dentry->d_inode,MAY_READ))
current->dumpable = 0; current->dumpable = 0;
flush_old_signals(current); flush_signal_handlers(current);
flush_old_files(current->files); flush_old_files(current->files);
return 0; return 0;
......
...@@ -59,7 +59,7 @@ struct inode_operations isofs_dir_inode_operations = ...@@ -59,7 +59,7 @@ struct inode_operations isofs_dir_inode_operations =
NULL, /* follow_link */ NULL, /* follow_link */
NULL, /* readpage */ NULL, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
isofs_bmap, /* bmap */ NULL, /* bmap */
NULL, /* truncate */ NULL, /* truncate */
NULL /* permission */ NULL /* permission */
}; };
......
...@@ -144,7 +144,7 @@ static int V1_sync_dindirect(struct inode *inode, unsigned short *diblock, ...@@ -144,7 +144,7 @@ static int V1_sync_dindirect(struct inode *inode, unsigned short *diblock,
return err; return err;
} }
int V1_minix_sync_file(struct inode * inode, struct file * file) static int V1_minix_sync_file(struct inode * inode, struct file * file)
{ {
int wait, err = 0; int wait, err = 0;
...@@ -305,7 +305,7 @@ static int V2_sync_tindirect(struct inode *inode, unsigned long *tiblock, ...@@ -305,7 +305,7 @@ static int V2_sync_tindirect(struct inode *inode, unsigned long *tiblock,
return err; return err;
} }
int V2_minix_sync_file(struct inode * inode, struct file * file) static int V2_minix_sync_file(struct inode * inode, struct file * file)
{ {
int wait, err = 0; int wait, err = 0;
......
...@@ -40,7 +40,7 @@ static void minix_commit_super (struct super_block * sb, ...@@ -40,7 +40,7 @@ static void minix_commit_super (struct super_block * sb,
sb->s_dirt = 0; sb->s_dirt = 0;
} }
void minix_write_super (struct super_block * sb) static void minix_write_super (struct super_block * sb)
{ {
struct minix_super_block * ms; struct minix_super_block * ms;
...@@ -55,7 +55,7 @@ void minix_write_super (struct super_block * sb) ...@@ -55,7 +55,7 @@ void minix_write_super (struct super_block * sb)
} }
void minix_put_super(struct super_block *sb) static void minix_put_super(struct super_block *sb)
{ {
int i; int i;
...@@ -86,7 +86,7 @@ static struct super_operations minix_sops = { ...@@ -86,7 +86,7 @@ static struct super_operations minix_sops = {
minix_remount minix_remount
}; };
int minix_remount (struct super_block * sb, int * flags, char * data) static int minix_remount (struct super_block * sb, int * flags, char * data)
{ {
struct minix_super_block * ms; struct minix_super_block * ms;
...@@ -162,7 +162,7 @@ static const char * minix_checkroot(struct super_block *s, struct inode *dir) ...@@ -162,7 +162,7 @@ static const char * minix_checkroot(struct super_block *s, struct inode *dir)
return errmsg; return errmsg;
} }
struct super_block *minix_read_super(struct super_block *s, void *data, static struct super_block *minix_read_super(struct super_block *s, void *data,
int silent) int silent)
{ {
struct buffer_head *bh; struct buffer_head *bh;
...@@ -326,7 +326,7 @@ struct super_block *minix_read_super(struct super_block *s, void *data, ...@@ -326,7 +326,7 @@ struct super_block *minix_read_super(struct super_block *s, void *data,
return NULL; return NULL;
} }
int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{ {
struct statfs tmp; struct statfs tmp;
...@@ -830,7 +830,7 @@ static void V2_minix_read_inode(struct inode * inode) ...@@ -830,7 +830,7 @@ static void V2_minix_read_inode(struct inode * inode)
/* /*
* The global function to read an inode. * The global function to read an inode.
*/ */
void minix_read_inode(struct inode * inode) static void minix_read_inode(struct inode * inode)
{ {
if (INODE_VERSION(inode) == MINIX_V1) if (INODE_VERSION(inode) == MINIX_V1)
V1_minix_read_inode(inode); V1_minix_read_inode(inode);
...@@ -916,7 +916,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode) ...@@ -916,7 +916,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
return bh; return bh;
} }
struct buffer_head *minix_update_inode(struct inode *inode) static struct buffer_head *minix_update_inode(struct inode *inode)
{ {
if (INODE_VERSION(inode) == MINIX_V1) if (INODE_VERSION(inode) == MINIX_V1)
return V1_minix_update_inode(inode); return V1_minix_update_inode(inode);
...@@ -924,7 +924,7 @@ struct buffer_head *minix_update_inode(struct inode *inode) ...@@ -924,7 +924,7 @@ struct buffer_head *minix_update_inode(struct inode *inode)
return V2_minix_update_inode(inode); return V2_minix_update_inode(inode);
} }
void minix_write_inode(struct inode * inode) static void minix_write_inode(struct inode * inode)
{ {
struct buffer_head *bh; struct buffer_head *bh;
......
...@@ -176,7 +176,7 @@ static int V1_trunc_dindirect(struct inode * inode, int offset, unsigned short * ...@@ -176,7 +176,7 @@ static int V1_trunc_dindirect(struct inode * inode, int offset, unsigned short *
return retry; return retry;
} }
void V1_minix_truncate(struct inode * inode) static void V1_minix_truncate(struct inode * inode)
{ {
int retry; int retry;
......
...@@ -993,7 +993,7 @@ struct inode_operations msdos_dir_inode_operations = { ...@@ -993,7 +993,7 @@ struct inode_operations msdos_dir_inode_operations = {
NULL, /* follow_link */ NULL, /* follow_link */
NULL, /* readpage */ NULL, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
fat_bmap, /* bmap */ NULL, /* bmap */
NULL, /* truncate */ NULL, /* truncate */
NULL, /* permission */ NULL, /* permission */
NULL, /* smap */ NULL, /* smap */
......
...@@ -230,6 +230,17 @@ nfs_readpage(struct file *file, struct page *page) ...@@ -230,6 +230,17 @@ nfs_readpage(struct file *file, struct page *page)
dprintk("NFS: nfs_readpage (%p %ld@%ld)\n", dprintk("NFS: nfs_readpage (%p %ld@%ld)\n",
page, PAGE_SIZE, page->offset); page, PAGE_SIZE, page->offset);
set_bit(PG_locked, &page->flags); set_bit(PG_locked, &page->flags);
/*
* Try to flush any pending writes to the file..
*
* NOTE! Because we own the page lock, there cannot
* be any new pending writes generated at this point.
*/
error = nfs_flush_pages(inode, 0, 0, 0);
if (error)
return error;
atomic_inc(&page->count); atomic_inc(&page->count);
if (!IS_SWAPFILE(inode) && !PageError(page) && if (!IS_SWAPFILE(inode) && !PageError(page) &&
NFS_SERVER(inode)->rsize >= PAGE_SIZE) NFS_SERVER(inode)->rsize >= PAGE_SIZE)
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
#define NFS_PARANOIA 1 #define NFS_PARANOIA 1
#define NFSDBG_FACILITY NFSDBG_PAGECACHE #define NFSDBG_FACILITY NFSDBG_PAGECACHE
static void nfs_wback_lock(struct rpc_task *task); static void nfs_wback_begin(struct rpc_task *task);
static void nfs_wback_result(struct rpc_task *task); static void nfs_wback_result(struct rpc_task *task);
static void nfs_cancel_request(struct nfs_wreq *req); static void nfs_cancel_request(struct nfs_wreq *req);
...@@ -73,55 +73,13 @@ static void nfs_cancel_request(struct nfs_wreq *req); ...@@ -73,55 +73,13 @@ static void nfs_cancel_request(struct nfs_wreq *req);
* Limit number of delayed writes * Limit number of delayed writes
*/ */
static int nr_write_requests = 0; static int nr_write_requests = 0;
static int nr_failed_requests = 0;
static struct rpc_wait_queue write_queue = RPC_INIT_WAITQ("write_chain"); static struct rpc_wait_queue write_queue = RPC_INIT_WAITQ("write_chain");
struct nfs_wreq * nfs_failed_requests = NULL;
/* Hack for future NFS swap support */ /* Hack for future NFS swap support */
#ifndef IS_SWAPFILE #ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0) # define IS_SWAPFILE(inode) (0)
#endif #endif
/*
* Unlock a page after writing it
*/
static inline void
nfs_unlock_page(struct page *page)
{
dprintk("NFS: unlock %ld\n", page->offset);
clear_bit(PG_locked, &page->flags);
wake_up(&page->wait);
#ifdef CONFIG_NFS_SWAP
/* async swap-out support */
if (test_and_clear_bit(PG_decr_after, &page->flags))
atomic_dec(&page->count);
if (test_and_clear_bit(PG_swap_unlock_after, &page->flags)) {
/*
* We're doing a swap, so check that this page is
* swap-cached and do the necessary cleanup.
*/
swap_after_unlock_page(page->offset);
}
#endif
}
/*
* Transfer a page lock to a write request waiting for it.
*/
static inline void
transfer_page_lock(struct nfs_wreq *req)
{
dprintk("NFS: transfer_page_lock\n");
req->wb_flags &= ~NFS_WRITE_WANTLOCK;
req->wb_flags |= NFS_WRITE_LOCKED;
rpc_wake_up_task(&req->wb_task);
dprintk("NFS: wake up task %d (flags %x)\n",
req->wb_task.tk_pid, req->wb_flags);
}
/* /*
* Write a page synchronously. * Write a page synchronously.
* Offset is the data offset within the page. * Offset is the data offset within the page.
...@@ -195,7 +153,6 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode, ...@@ -195,7 +153,6 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
inode->i_ino, fattr.fileid); inode->i_ino, fattr.fileid);
} }
nfs_unlock_page(page);
return written? written : result; return written? written : result;
} }
...@@ -220,11 +177,13 @@ remove_write_request(struct nfs_wreq **q, struct nfs_wreq *wreq) ...@@ -220,11 +177,13 @@ remove_write_request(struct nfs_wreq **q, struct nfs_wreq *wreq)
} }
/* /*
* Find a write request for a given page * Find a non-busy write request for a given page to
* try to combine with.
*/ */
static inline struct nfs_wreq * static inline struct nfs_wreq *
find_write_request(struct inode *inode, struct page *page) find_write_request(struct inode *inode, struct page *page)
{ {
pid_t pid = current->pid;
struct nfs_wreq *head, *req; struct nfs_wreq *head, *req;
dprintk("NFS: find_write_request(%x/%ld, %p)\n", dprintk("NFS: find_write_request(%x/%ld, %p)\n",
...@@ -232,8 +191,21 @@ find_write_request(struct inode *inode, struct page *page) ...@@ -232,8 +191,21 @@ find_write_request(struct inode *inode, struct page *page)
if (!(req = head = NFS_WRITEBACK(inode))) if (!(req = head = NFS_WRITEBACK(inode)))
return NULL; return NULL;
do { do {
if (req->wb_page == page) /*
* We can't combine with canceled requests or
* requests that have already been started..
*/
if (req->wb_flags & (NFS_WRITE_CANCELLED | NFS_WRITE_INPROGRESS))
continue;
if (req->wb_page == page && req->wb_pid == pid)
return req; return req;
/*
* Ehh, don't keep too many tasks queued..
*/
rpc_wake_up_task(&req->wb_task);
} while ((req = WB_NEXT(req)) != head); } while ((req = WB_NEXT(req)) != head);
return NULL; return NULL;
} }
...@@ -259,65 +231,14 @@ nfs_find_dentry_request(struct inode *inode, struct dentry *dentry) ...@@ -259,65 +231,14 @@ nfs_find_dentry_request(struct inode *inode, struct dentry *dentry)
return found; return found;
} }
/*
* Find a failed write request by pid
*/
static struct nfs_wreq *
find_failed_request(struct inode *inode, pid_t pid)
{
struct nfs_wreq *head, *req;
req = head = nfs_failed_requests;
while (req != NULL) {
if (req->wb_inode == inode && (pid == 0 || req->wb_pid == pid))
return req;
if ((req = WB_NEXT(req)) == head)
break;
}
return NULL;
}
/*
* Add a request to the failed list.
*/
static void
append_failed_request(struct nfs_wreq * req)
{
static int old_max = 16;
append_write_request(&nfs_failed_requests, req);
nr_failed_requests++;
if (nr_failed_requests >= old_max) {
printk("NFS: %d failed requests\n", nr_failed_requests);
old_max = old_max << 1;
}
}
/*
* Remove a request from the failed list and free it.
*/
static void
remove_failed_request(struct nfs_wreq * req)
{
remove_write_request(&nfs_failed_requests, req);
kfree(req);
nr_failed_requests--;
}
/* /*
* Find and release all failed requests for this inode. * Find and release all failed requests for this inode.
*/ */
int int
nfs_check_failed_request(struct inode * inode) nfs_check_failed_request(struct inode * inode)
{ {
struct nfs_wreq * req; /* FIXME! */
int found = 0; return 0;
while ((req = find_failed_request(inode, 0)) != NULL) {
remove_failed_request(req);
found++;
}
return found;
} }
/* /*
...@@ -334,6 +255,10 @@ update_write_request(struct nfs_wreq *req, unsigned int first, ...@@ -334,6 +255,10 @@ update_write_request(struct nfs_wreq *req, unsigned int first,
dprintk("nfs: trying to update write request %p\n", req); dprintk("nfs: trying to update write request %p\n", req);
/* not contiguous? */
if (rqlast < first || last < rqfirst)
return 0;
/* Check the credentials associated with this write request. /* Check the credentials associated with this write request.
* If the buffer is owned by the same user, we can happily * If the buffer is owned by the same user, we can happily
* add our data without risking server permission problems. * add our data without risking server permission problems.
...@@ -349,12 +274,25 @@ update_write_request(struct nfs_wreq *req, unsigned int first, ...@@ -349,12 +274,25 @@ update_write_request(struct nfs_wreq *req, unsigned int first,
rqfirst = first; rqfirst = first;
if (rqlast < last) if (rqlast < last)
rqlast = last; rqlast = last;
req->wb_offset = rqfirst; req->wb_offset = rqfirst;
req->wb_bytes = rqlast - rqfirst; req->wb_bytes = rqlast - rqfirst;
req->wb_count++;
return 1; return 1;
} }
static inline void
free_write_request(struct nfs_wreq * req)
{
if (!--req->wb_count) {
struct inode *inode = req->wb_inode;
remove_write_request(&NFS_WRITEBACK(inode), req);
kfree(req);
nr_write_requests--;
}
}
/* /*
* Create and initialize a writeback request * Create and initialize a writeback request
*/ */
...@@ -371,8 +309,7 @@ create_write_request(struct dentry *dentry, struct inode *inode, ...@@ -371,8 +309,7 @@ create_write_request(struct dentry *dentry, struct inode *inode,
page->offset + offset, bytes); page->offset + offset, bytes);
/* FIXME: Enforce hard limit on number of concurrent writes? */ /* FIXME: Enforce hard limit on number of concurrent writes? */
wreq = (struct nfs_wreq *) kmalloc(sizeof(*wreq), GFP_KERNEL);
wreq = (struct nfs_wreq *) kmalloc(sizeof(*wreq), GFP_USER);
if (!wreq) if (!wreq)
goto out_fail; goto out_fail;
memset(wreq, 0, sizeof(*wreq)); memset(wreq, 0, sizeof(*wreq));
...@@ -380,7 +317,7 @@ create_write_request(struct dentry *dentry, struct inode *inode, ...@@ -380,7 +317,7 @@ create_write_request(struct dentry *dentry, struct inode *inode,
task = &wreq->wb_task; task = &wreq->wb_task;
rpc_init_task(task, clnt, nfs_wback_result, RPC_TASK_NFSWRITE); rpc_init_task(task, clnt, nfs_wback_result, RPC_TASK_NFSWRITE);
task->tk_calldata = wreq; task->tk_calldata = wreq;
task->tk_action = nfs_wback_lock; task->tk_action = nfs_wback_begin;
rpcauth_lookupcred(task); /* Obtain user creds */ rpcauth_lookupcred(task); /* Obtain user creds */
if (task->tk_status < 0) if (task->tk_status < 0)
...@@ -393,6 +330,7 @@ create_write_request(struct dentry *dentry, struct inode *inode, ...@@ -393,6 +330,7 @@ create_write_request(struct dentry *dentry, struct inode *inode,
wreq->wb_page = page; wreq->wb_page = page;
wreq->wb_offset = offset; wreq->wb_offset = offset;
wreq->wb_bytes = bytes; wreq->wb_bytes = bytes;
wreq->wb_count = 2; /* One for the IO, one for us */
atomic_inc(&page->count); atomic_inc(&page->count);
...@@ -414,8 +352,7 @@ create_write_request(struct dentry *dentry, struct inode *inode, ...@@ -414,8 +352,7 @@ create_write_request(struct dentry *dentry, struct inode *inode,
* Schedule a writeback RPC call. * Schedule a writeback RPC call.
* If the server is congested, don't add to our backlog of queued * If the server is congested, don't add to our backlog of queued
* requests but call it synchronously. * requests but call it synchronously.
* The function returns false if the page has been unlocked as the * The function returns whether we should wait for the thing or not.
* consequence of a synchronous write call.
* *
* FIXME: Here we could walk the inode's lock list to see whether the * FIXME: Here we could walk the inode's lock list to see whether the
* page we're currently writing to has been write-locked by the caller. * page we're currently writing to has been write-locked by the caller.
...@@ -438,7 +375,6 @@ schedule_write_request(struct nfs_wreq *req, int sync) ...@@ -438,7 +375,6 @@ schedule_write_request(struct nfs_wreq *req, int sync)
dprintk("NFS: %4d schedule_write_request (sync)\n", dprintk("NFS: %4d schedule_write_request (sync)\n",
task->tk_pid); task->tk_pid);
/* Page is already locked */ /* Page is already locked */
req->wb_flags |= NFS_WRITE_LOCKED;
rpc_clnt_sigmask(clnt, &oldmask); rpc_clnt_sigmask(clnt, &oldmask);
rpc_execute(task); rpc_execute(task);
rpc_clnt_sigunmask(clnt, &oldmask); rpc_clnt_sigunmask(clnt, &oldmask);
...@@ -450,39 +386,38 @@ schedule_write_request(struct nfs_wreq *req, int sync) ...@@ -450,39 +386,38 @@ schedule_write_request(struct nfs_wreq *req, int sync)
rpc_sleep_on(&write_queue, task, NULL, NULL); rpc_sleep_on(&write_queue, task, NULL, NULL);
} }
return sync == 0; return sync;
} }
/* /*
* Wait for request to complete * Wait for request to complete.
* This is almost a copy of __wait_on_page
*/ */
static inline int static int
wait_on_write_request(struct nfs_wreq *req) wait_on_write_request(struct nfs_wreq *req)
{ {
struct rpc_clnt *clnt = NFS_CLIENT(req->wb_inode);
struct wait_queue wait = { current, NULL }; struct wait_queue wait = { current, NULL };
struct page *page = req->wb_page;
int retval;
sigset_t oldmask; sigset_t oldmask;
struct rpc_clnt *clnt = NFS_CLIENT(req->wb_inode); int retval;
/* Make sure it's started.. */
if (!WB_INPROGRESS(req))
rpc_wake_up_task(&req->wb_task);
rpc_clnt_sigmask(clnt, &oldmask); rpc_clnt_sigmask(clnt, &oldmask);
add_wait_queue(&page->wait, &wait); add_wait_queue(&req->wb_wait, &wait);
atomic_inc(&page->count);
for (;;) { for (;;) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
retval = 0; retval = 0;
if (!PageLocked(page)) if (req->wb_flags & NFS_WRITE_COMPLETE)
break; break;
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
if (signalled()) if (signalled())
break; break;
schedule(); schedule();
} }
remove_wait_queue(&page->wait, &wait); remove_wait_queue(&req->wb_wait, &wait);
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
/* N.B. page may have been unused, so we must use free_page() */
free_page(page_address(page));
rpc_clnt_sigunmask(clnt, &oldmask); rpc_clnt_sigunmask(clnt, &oldmask);
return retval; return retval;
} }
...@@ -510,7 +445,8 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig ...@@ -510,7 +445,8 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig
struct dentry *dentry = file->f_dentry; struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct nfs_wreq *req; struct nfs_wreq *req;
int status = 0, page_locked = 1; int synchronous = sync;
int retval;
dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n", dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name,
...@@ -526,143 +462,54 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig ...@@ -526,143 +462,54 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig
* After returning, generic_file_write will wait on the * After returning, generic_file_write will wait on the
* page and retry the update. * page and retry the update.
*/ */
if ((req = find_write_request(inode, page)) != NULL) { req = find_write_request(inode, page);
if (update_write_request(req, offset, count)) if (req && update_write_request(req, offset, count))
goto updated; goto updated;
dprintk("NFS: wake up conflicting write request.\n"); /*
transfer_page_lock(req); * If wsize is smaller than page size, update and write
return 0;
}
/* If wsize is smaller than page size, update and write
* page synchronously. * page synchronously.
*/ */
if (NFS_SERVER(inode)->wsize < PAGE_SIZE) if (NFS_SERVER(inode)->wsize < PAGE_SIZE)
return nfs_writepage_sync(dentry, inode, page, offset, count); return nfs_writepage_sync(dentry, inode, page, offset, count);
/* Create the write request. */ /* Create the write request. */
status = -ENOBUFS;
req = create_write_request(dentry, inode, page, offset, count); req = create_write_request(dentry, inode, page, offset, count);
if (!req) if (!req)
goto done; return -ENOBUFS;
/*
* Ok, there's another user of this page with the new request..
* Increment the usage count, and schedule the request (the
* end of the request will drop the usage count..)
*/
atomic_inc(&page->count);
/* Schedule request */ /* Schedule request */
page_locked = schedule_write_request(req, sync); synchronous = schedule_write_request(req, sync);
updated: updated:
if (req->wb_bytes == PAGE_SIZE) if (req->wb_bytes == PAGE_SIZE)
set_bit(PG_uptodate, &page->flags); set_bit(PG_uptodate, &page->flags);
/* retval = count;
* If we wrote up to the end of the chunk, transmit request now. if (synchronous) {
* We should be a bit more intelligent about detecting whether a int status = wait_on_write_request(req);
* process accesses the file sequentially or not. if (status) {
*/
if (page_locked && (offset + count >= PAGE_SIZE || sync))
req->wb_flags |= NFS_WRITE_WANTLOCK;
/* If the page was written synchronously, return any error that
* may have happened; otherwise return the write count. */
if (page_locked || (status = nfs_write_error(inode)) >= 0)
status = count;
done:
/* Unlock page and wake up anyone sleeping on it */
if (page_locked) {
if (req && WB_WANTLOCK(req)) {
transfer_page_lock(req);
/* rpc_execute(&req->wb_task); */
if (sync) {
/* if signalled, ensure request is cancelled */
if ((count = wait_on_write_request(req)) != 0) {
nfs_cancel_request(req); nfs_cancel_request(req);
status = count; retval = status;
}
if ((count = nfs_write_error(inode)) < 0)
status = count;
}
} else {
if (status < 0) {
printk("NFS: %s/%s write failed, clearing bit\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
clear_bit(PG_uptodate, &page->flags);
}
nfs_unlock_page(page);
}
}
dprintk("NFS: nfs_updatepage returns %d (isize %ld)\n",
status, inode->i_size);
return status;
}
/*
* Flush out a dirty page.
*/
static void
nfs_flush_request(struct nfs_wreq *req)
{
struct page *page = req->wb_page;
#ifdef NFS_DEBUG_VERBOSE
if (req->wb_inode != page->inode)
printk("NFS: inode %ld no longer has page %p\n", req->wb_inode->i_ino, page);
#endif
dprintk("NFS: nfs_flush_request(%s/%s, @%ld)\n",
req->wb_dentry->d_parent->d_name.name,
req->wb_dentry->d_name.name, page->offset);
req->wb_flags |= NFS_WRITE_WANTLOCK;
if (!test_and_set_bit(PG_locked, &page->flags)) {
transfer_page_lock(req);
} else { } else {
printk(KERN_WARNING "NFS oops in %s: can't lock page!\n", status = req->wb_status;
__FUNCTION__); if (status < 0)
rpc_wake_up_task(&req->wb_task); retval = status;
} }
}
/*
* Flush writeback requests. See nfs_flush_dirty_pages for details.
*/
static struct nfs_wreq *
nfs_flush_pages(struct inode *inode, pid_t pid, off_t offset, off_t len,
int invalidate)
{
struct nfs_wreq *head, *req, *last = NULL;
off_t rqoffset, rqend, end;
end = len? offset + len : 0x7fffffffUL; if (retval < 0)
clear_bit(PG_uptodate, &page->flags);
req = head = NFS_WRITEBACK(inode);
while (req != NULL) {
dprintk("NFS: %4d nfs_flush inspect %s/%s @%ld fl %x\n",
req->wb_task.tk_pid,
req->wb_dentry->d_parent->d_name.name,
req->wb_dentry->d_name.name,
req->wb_page->offset, req->wb_flags);
rqoffset = req->wb_page->offset + req->wb_offset;
rqend = rqoffset + req->wb_bytes;
if (rqoffset < end && offset < rqend &&
(pid == 0 || req->wb_pid == pid)) {
if (!WB_INPROGRESS(req) && !WB_HAVELOCK(req)) {
#ifdef NFS_DEBUG_VERBOSE
printk("nfs_flush: flushing inode=%ld, %d @ %lu\n",
req->wb_inode->i_ino, req->wb_bytes, rqoffset);
#endif
nfs_flush_request(req);
}
last = req;
}
if (invalidate)
req->wb_flags |= NFS_WRITE_INVALIDATE;
if ((req = WB_NEXT(req)) == head)
break;
} }
return last; free_write_request(req);
return retval;
} }
/* /*
...@@ -699,53 +546,67 @@ nfs_cancel_dirty(struct inode *inode, pid_t pid) ...@@ -699,53 +546,67 @@ nfs_cancel_dirty(struct inode *inode, pid_t pid)
} }
/* /*
* Flush out all dirty pages belonging to a certain user process and * Try to flush any dirty pages, returning a success marker..
* maybe wait for the RPC calls to complete.
* *
* Another purpose of this function is sync()ing a file range before a * Unlike "nfs_flush_dirty_pages()" this does not invalidate
* write lock is released. This is what offset and length are for, even if * the writes if it is interrupted. The caller will instead
* this isn't used by the nlm module yet. * look at the error code and gracefully fail to do what it
* wanted to do.
*/ */
int int
nfs_flush_dirty_pages(struct inode *inode, pid_t pid, off_t offset, off_t len) nfs_flush_pages(struct inode *inode, pid_t pid, off_t offset, off_t len)
{ {
struct nfs_wreq *last = NULL; int retval;
int result = 0;
dprintk("NFS: flush_dirty_pages(%x/%ld for pid %d %ld/%ld)\n", do {
inode->i_dev, inode->i_ino, current->pid, offset, len); struct nfs_wreq *req = NFS_WRITEBACK(inode);
struct nfs_wreq *head = req;
if (!req)
return 0;
/*
* Iterate over all outstanding write requests,
* looking for any that are ours..
*/
for (;;) { for (;;) {
/* Flush all pending writes for the pid and file region */ if (!(req->wb_flags & NFS_WRITE_COMPLETE)) {
last = nfs_flush_pages(inode, pid, offset, len, 0); if (!pid || req->wb_pid == pid)
if (last == NULL)
break;
result = wait_on_write_request(last);
if (result) {
nfs_cancel_dirty(inode,pid);
break; break;
} }
req = WB_NEXT(req);
if (req == head)
return 0;
} }
return result; req->wb_count++;
retval = wait_on_write_request(req);
free_write_request(req);
} while (!retval);
return retval;
} }
/* /*
* Flush out any pending write requests and flag that they be discarded * Flush out all dirty pages belonging to a certain user process and
* after the write is complete. * maybe wait for the RPC calls to complete.
* *
* This function is called from nfs_refresh_inode just before it calls * Another purpose of this function is sync()ing a file range before a
* invalidate_inode_pages. After nfs_flush_pages returns, we can be sure * write lock is released. This is what offset and length are for, even if
* that all dirty pages are locked, so that invalidate_inode_pages does * this isn't used by the nlm module yet.
* not throw away any dirty pages.
*/ */
int
nfs_flush_dirty_pages(struct inode *inode, pid_t pid, off_t offset, off_t len)
{
int retval = nfs_flush_pages(inode, pid, offset, len);
if (retval)
nfs_cancel_dirty(inode,pid);
return retval;
}
void void
nfs_invalidate_pages(struct inode *inode) nfs_invalidate_pages(struct inode *inode)
{ {
dprintk("NFS: nfs_invalidate_pages(%x/%ld)\n", nfs_cancel_dirty(inode,0);
inode->i_dev, inode->i_ino);
nfs_flush_pages(inode, 0, 0, 0, 1);
} }
/* /*
...@@ -783,21 +644,8 @@ nfs_truncate_dirty_pages(struct inode *inode, unsigned long offset) ...@@ -783,21 +644,8 @@ nfs_truncate_dirty_pages(struct inode *inode, unsigned long offset)
int int
nfs_check_error(struct inode *inode) nfs_check_error(struct inode *inode)
{ {
struct nfs_wreq *req; /* FIXME! */
int status = 0; return 0;
dprintk("nfs: checking for write error inode %04x/%ld\n",
inode->i_dev, inode->i_ino);
req = find_failed_request(inode, current->pid);
if (req) {
dprintk("nfs: write error %d inode %04x/%ld\n",
req->wb_task.tk_status, inode->i_dev, inode->i_ino);
status = req->wb_task.tk_status;
remove_failed_request(req);
}
return status;
} }
/* /*
...@@ -807,23 +655,16 @@ nfs_check_error(struct inode *inode) ...@@ -807,23 +655,16 @@ nfs_check_error(struct inode *inode)
* set up the RPC call info, and pass to the call FSM. * set up the RPC call info, and pass to the call FSM.
*/ */
static void static void
nfs_wback_lock(struct rpc_task *task) nfs_wback_begin(struct rpc_task *task)
{ {
struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata; struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata;
struct page *page = req->wb_page; struct page *page = req->wb_page;
struct dentry *dentry = req->wb_dentry; struct dentry *dentry = req->wb_dentry;
dprintk("NFS: %4d nfs_wback_lock (%s/%s, status=%d flags=%x)\n", dprintk("NFS: %4d nfs_wback_begin (%s/%s, status=%d flags=%x)\n",
task->tk_pid, dentry->d_parent->d_name.name, task->tk_pid, dentry->d_parent->d_name.name,
dentry->d_name.name, task->tk_status, req->wb_flags); dentry->d_name.name, task->tk_status, req->wb_flags);
if (!WB_HAVELOCK(req))
req->wb_flags |= NFS_WRITE_WANTLOCK;
if (WB_WANTLOCK(req) && test_and_set_bit(PG_locked, &page->flags))
goto out_locked;
req->wb_flags &= ~NFS_WRITE_WANTLOCK;
req->wb_flags |= NFS_WRITE_LOCKED;
task->tk_status = 0; task->tk_status = 0;
/* Setup the task struct for a writeback call */ /* Setup the task struct for a writeback call */
...@@ -836,12 +677,6 @@ nfs_wback_lock(struct rpc_task *task) ...@@ -836,12 +677,6 @@ nfs_wback_lock(struct rpc_task *task)
req->wb_flags |= NFS_WRITE_INPROGRESS; req->wb_flags |= NFS_WRITE_INPROGRESS;
return; return;
out_locked:
printk("NFS: page already locked in writeback_lock!\n");
task->tk_timeout = 2 * HZ;
rpc_sleep_on(&write_queue, task, NULL, NULL);
return;
} }
/* /*
...@@ -861,15 +696,10 @@ nfs_wback_result(struct rpc_task *task) ...@@ -861,15 +696,10 @@ nfs_wback_result(struct rpc_task *task)
/* Set the WRITE_COMPLETE flag, but leave WRITE_INPROGRESS set */ /* Set the WRITE_COMPLETE flag, but leave WRITE_INPROGRESS set */
req->wb_flags |= NFS_WRITE_COMPLETE; req->wb_flags |= NFS_WRITE_COMPLETE;
req->wb_status = status;
if (status < 0) { if (status < 0) {
/* req->wb_flags |= NFS_WRITE_INVALIDATE;
* An error occurred. Report the error back to the
* application by adding the request to the failed
* requests list.
*/
if (find_failed_request(inode, req->wb_pid))
status = 0;
clear_bit(PG_uptodate, &page->flags);
} else if (!WB_CANCELLED(req)) { } else if (!WB_CANCELLED(req)) {
struct nfs_fattr *fattr = &req->wb_fattr; struct nfs_fattr *fattr = &req->wb_fattr;
/* Update attributes as result of writeback. /* Update attributes as result of writeback.
...@@ -899,31 +729,27 @@ nfs_wback_result(struct rpc_task *task) ...@@ -899,31 +729,27 @@ nfs_wback_result(struct rpc_task *task)
} }
} }
/*
* This call might block, so we defer removing the request
* from the inode's writeback list.
*/
rpc_release_task(task); rpc_release_task(task);
if (WB_INVALIDATE(req)) if (WB_INVALIDATE(req))
clear_bit(PG_uptodate, &page->flags); clear_bit(PG_uptodate, &page->flags);
if (WB_HAVELOCK(req))
nfs_unlock_page(page);
/* __free_page(page);
* Now it's safe to remove the request from the inode's
* writeback list and wake up any tasks sleeping on it.
* If the request failed, add it to the failed list.
*/
remove_write_request(&NFS_WRITEBACK(inode), req);
if (status >= 0) wake_up(&req->wb_wait);
kfree(req);
else {
dprintk("NFS: %4d saving write failure code\n", task->tk_pid);
append_failed_request(req);
}
free_page(page_address(page)); /*
nr_write_requests--; * FIXME!
*
* We should not free the request here if it has pending
* error status on it. We should just leave it around, to
* let the error be collected later. However, the error
* collecting routines are too stupid for that right now,
* so we just drop the error on the floor at this point
* for any async writes.
*
* This should not be a major headache to fix, but I want
* to validate basic operations first.
*/
free_write_request(req);
} }
...@@ -180,11 +180,7 @@ static struct file_operations qnx4_file_operations = ...@@ -180,11 +180,7 @@ static struct file_operations qnx4_file_operations =
struct inode_operations qnx4_file_inode_operations = struct inode_operations qnx4_file_inode_operations =
{ {
&qnx4_file_operations, /* default file operations */ &qnx4_file_operations, /* default file operations */
#ifdef CONFIG_QNX4FS_RW NULL, /* create? It's not a directory */
qnx4_create, /* create */
#else
NULL,
#endif
NULL, /* lookup */ NULL, /* lookup */
NULL, /* link */ NULL, /* link */
NULL, /* unlink */ NULL, /* unlink */
......
...@@ -32,11 +32,7 @@ static struct dentry *qnx4_follow_link(struct dentry *, struct dentry *); ...@@ -32,11 +32,7 @@ static struct dentry *qnx4_follow_link(struct dentry *, struct dentry *);
struct inode_operations qnx4_symlink_inode_operations = struct inode_operations qnx4_symlink_inode_operations =
{ {
NULL, /* no file-operations */ NULL, /* no file-operations */
#ifdef CONFIG_QNX4FS_RW NULL, /* create */
qnx4_create, /* create */
#else
NULL,
#endif
NULL, /* lookup */ NULL, /* lookup */
NULL, /* link */ NULL, /* link */
NULL, /* unlink */ NULL, /* unlink */
......
...@@ -6,12 +6,9 @@ ...@@ -6,12 +6,9 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/types.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -195,40 +195,15 @@ smb_writepage(struct file *file, struct page *page) ...@@ -195,40 +195,15 @@ smb_writepage(struct file *file, struct page *page)
} }
static int static int
smb_updatepage(struct file *file, struct page *page, const char *buffer, smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count, int sync)
unsigned long offset, unsigned int count, int sync)
{ {
struct dentry *dentry = file->f_dentry; struct dentry *dentry = file->f_dentry;
unsigned long page_addr = page_address(page);
int result;
pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n", pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name,
count, page->offset+offset, sync); count, page->offset+offset, sync);
#ifdef SMBFS_PARANOIA return smb_writepage_sync(dentry, page, offset, count);
if (test_bit(PG_locked, &page->flags))
printk("smb_updatepage: page already locked!\n");
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
if (copy_from_user((char *) page_addr + offset, buffer, count))
goto bad_fault;
result = smb_writepage_sync(dentry, page, offset, count);
out:
free_page(page_addr);
return result;
bad_fault:
#ifdef SMBFS_PARANOIA
printk("smb_updatepage: fault at addr=%lu, offset=%lu, buffer=%p\n",
page_addr, offset, buffer);
#endif
result = -EFAULT;
clear_bit(PG_uptodate, &page->flags);
smb_unlock_page(page);
goto out;
} }
static ssize_t static ssize_t
......
...@@ -220,7 +220,7 @@ struct inode_operations ufs_dir_inode_operations = { ...@@ -220,7 +220,7 @@ struct inode_operations ufs_dir_inode_operations = {
NULL, /* follow_link */ NULL, /* follow_link */
NULL, /* readpage */ NULL, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
ufs_bmap, /* bmap */ NULL, /* bmap */
NULL, /* truncate */ NULL, /* truncate */
ufs_permission, /* permission */ ufs_permission, /* permission */
NULL, /* smap */ NULL, /* smap */
......
...@@ -1846,7 +1846,7 @@ struct inode_operations vfat_dir_inode_operations = { ...@@ -1846,7 +1846,7 @@ struct inode_operations vfat_dir_inode_operations = {
NULL, /* followlink */ NULL, /* followlink */
NULL, /* readpage */ NULL, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
fat_bmap, /* bmap */ NULL, /* bmap */
NULL, /* truncate */ NULL, /* truncate */
NULL /* permission */ NULL /* permission */
}; };
......
...@@ -101,31 +101,29 @@ struct nfs_wreq { ...@@ -101,31 +101,29 @@ struct nfs_wreq {
struct dentry * wb_dentry; /* dentry referenced */ struct dentry * wb_dentry; /* dentry referenced */
struct inode * wb_inode; /* inode referenced */ struct inode * wb_inode; /* inode referenced */
struct page * wb_page; /* page to be written */ struct page * wb_page; /* page to be written */
struct wait_queue * wb_wait; /* wait for completion */
unsigned int wb_offset; /* offset within page */ unsigned int wb_offset; /* offset within page */
unsigned int wb_bytes; /* dirty range */ unsigned int wb_bytes; /* dirty range */
unsigned int wb_count; /* user count */
int wb_status;
pid_t wb_pid; /* owner process */ pid_t wb_pid; /* owner process */
unsigned short wb_flags; /* status flags */ unsigned short wb_flags; /* status flags */
struct nfs_writeargs wb_args; /* NFS RPC stuff */ struct nfs_writeargs wb_args; /* NFS RPC stuff */
struct nfs_fattr wb_fattr; /* file attributes */ struct nfs_fattr wb_fattr; /* file attributes */
}; };
#define wb_status wb_task.tk_status
#define WB_NEXT(req) ((struct nfs_wreq *) ((req)->wb_list.next)) #define WB_NEXT(req) ((struct nfs_wreq *) ((req)->wb_list.next))
/* /*
* Various flags for wb_flags * Various flags for wb_flags
*/ */
#define NFS_WRITE_WANTLOCK 0x0001 /* needs to lock page */
#define NFS_WRITE_LOCKED 0x0002 /* holds lock on page */
#define NFS_WRITE_CANCELLED 0x0004 /* has been cancelled */ #define NFS_WRITE_CANCELLED 0x0004 /* has been cancelled */
#define NFS_WRITE_UNCOMMITTED 0x0008 /* written but uncommitted (NFSv3) */ #define NFS_WRITE_UNCOMMITTED 0x0008 /* written but uncommitted (NFSv3) */
#define NFS_WRITE_INVALIDATE 0x0010 /* invalidate after write */ #define NFS_WRITE_INVALIDATE 0x0010 /* invalidate after write */
#define NFS_WRITE_INPROGRESS 0x0100 /* RPC call in progress */ #define NFS_WRITE_INPROGRESS 0x0100 /* RPC call in progress */
#define NFS_WRITE_COMPLETE 0x0200 /* RPC call completed */ #define NFS_WRITE_COMPLETE 0x0200 /* RPC call completed */
#define WB_WANTLOCK(req) ((req)->wb_flags & NFS_WRITE_WANTLOCK)
#define WB_HAVELOCK(req) ((req)->wb_flags & NFS_WRITE_LOCKED)
#define WB_CANCELLED(req) ((req)->wb_flags & NFS_WRITE_CANCELLED) #define WB_CANCELLED(req) ((req)->wb_flags & NFS_WRITE_CANCELLED)
#define WB_UNCOMMITTED(req) ((req)->wb_flags & NFS_WRITE_UNCOMMITTED) #define WB_UNCOMMITTED(req) ((req)->wb_flags & NFS_WRITE_UNCOMMITTED)
#define WB_INVALIDATE(req) ((req)->wb_flags & NFS_WRITE_INVALIDATE) #define WB_INVALIDATE(req) ((req)->wb_flags & NFS_WRITE_INVALIDATE)
...@@ -217,6 +215,7 @@ extern int nfs_writepage(struct file *, struct page *); ...@@ -217,6 +215,7 @@ extern int nfs_writepage(struct file *, struct page *);
extern int nfs_find_dentry_request(struct inode *, struct dentry *); extern int nfs_find_dentry_request(struct inode *, struct dentry *);
extern int nfs_check_failed_request(struct inode *); extern int nfs_check_failed_request(struct inode *);
extern int nfs_check_error(struct inode *); extern int nfs_check_error(struct inode *);
extern int nfs_flush_pages(struct inode *, pid_t, off_t, off_t);
extern int nfs_flush_dirty_pages(struct inode *, pid_t, off_t, off_t); extern int nfs_flush_dirty_pages(struct inode *, pid_t, off_t, off_t);
extern int nfs_truncate_dirty_pages(struct inode *, unsigned long); extern int nfs_truncate_dirty_pages(struct inode *, unsigned long);
extern void nfs_invalidate_pages(struct inode *); extern void nfs_invalidate_pages(struct inode *);
...@@ -245,13 +244,10 @@ nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry) ...@@ -245,13 +244,10 @@ nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
return _nfs_revalidate_inode(server, dentry); return _nfs_revalidate_inode(server, dentry);
} }
extern struct nfs_wreq * nfs_failed_requests;
static inline int static inline int
nfs_write_error(struct inode *inode) nfs_write_error(struct inode *inode)
{ {
if (nfs_failed_requests == NULL) return NFS_WRITEBACK(inode) && nfs_check_error(inode);
return 0;
return nfs_check_error(inode);
} }
/* NFS root */ /* NFS root */
......
...@@ -20,7 +20,6 @@ extern unsigned long event; ...@@ -20,7 +20,6 @@ extern unsigned long event;
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/sem.h> #include <linux/sem.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/capability.h>
#include <linux/securebits.h> #include <linux/securebits.h>
/* /*
...@@ -65,11 +64,9 @@ extern int nr_running, nr_tasks; ...@@ -65,11 +64,9 @@ extern int nr_running, nr_tasks;
extern int last_pid; extern int last_pid;
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/signal.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/resource.h> #include <linux/resource.h>
#include <linux/ptrace.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <asm/processor.h> #include <asm/processor.h>
......
...@@ -11,16 +11,11 @@ ...@@ -11,16 +11,11 @@
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/types.h> #include <linux/sched.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -34,7 +29,6 @@ ...@@ -34,7 +29,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/bugs.h> #include <asm/bugs.h>
......
...@@ -45,18 +45,13 @@ ...@@ -45,18 +45,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#ifdef CONFIG_BSD_PROCESS_ACCT #ifdef CONFIG_BSD_PROCESS_ACCT
#include <linux/fs.h> #include <linux/sched.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/types.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/acct.h> #include <linux/acct.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/file.h> #include <linux/file.h>
......
...@@ -6,10 +6,8 @@ ...@@ -6,10 +6,8 @@
*/ */
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/module.h> #include <linux/module.h>
......
...@@ -7,16 +7,12 @@ ...@@ -7,16 +7,12 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/resource.h> #include <linux/resource.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/tty.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
......
...@@ -14,17 +14,13 @@ ...@@ -14,17 +14,13 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/system.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -9,10 +9,8 @@ ...@@ -9,10 +9,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/types.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -6,13 +6,10 @@ ...@@ -6,13 +6,10 @@
/* These are all the functions necessary to implement itimers */ /* These are all the functions necessary to implement itimers */
#include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/time.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -12,10 +12,8 @@ ...@@ -12,10 +12,8 @@
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/types.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/signal.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -11,32 +11,24 @@ ...@@ -11,32 +11,24 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/sched.h>
#include <linux/fs.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/ptrace.h>
#include <linux/sys.h> #include <linux/sys.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <linux/termios.h> #include <linux/termios.h>
#include <linux/tqueue.h> #include <linux/tqueue.h>
#include <linux/tty.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sem.h>
#include <linux/minix_fs.h> #include <linux/minix_fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/random.h> #include <linux/random.h>
...@@ -51,9 +43,6 @@ ...@@ -51,9 +43,6 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/time.h>
#include <asm/spinlock.h>
#if defined(CONFIG_PROC_FS) #if defined(CONFIG_PROC_FS)
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
...@@ -62,9 +51,6 @@ ...@@ -62,9 +51,6 @@
#include <linux/kmod.h> #include <linux/kmod.h>
#endif #endif
#include <asm/irq.h> #include <asm/irq.h>
#ifdef __SMP__
#include <linux/smp.h>
#endif
extern char *get_options(char *str, int *ints); extern char *get_options(char *str, int *ints);
extern void set_device_ro(kdev_t dev,int flag); extern void set_device_ro(kdev_t dev,int flag);
......
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/sched.h>
#include <linux/mm.h> /* defines GFP_KERNEL */ #include <linux/mm.h> /* defines GFP_KERNEL */
#include <linux/string.h> #include <linux/string.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched.h>
#include <linux/config.h> #include <linux/config.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
......
...@@ -10,10 +10,8 @@ ...@@ -10,10 +10,8 @@
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/smp.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sysrq.h> #include <linux/sysrq.h>
......
...@@ -16,16 +16,12 @@ ...@@ -16,16 +16,12 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/tty.h>
#include <linux/tty_driver.h> #include <linux/tty_driver.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define LOG_BUF_LEN (16384) #define LOG_BUF_LEN (16384)
......
...@@ -8,9 +8,7 @@ ...@@ -8,9 +8,7 @@
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -16,25 +16,18 @@ ...@@ -16,25 +16,18 @@
* current-task * current-task
*/ */
#include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/fdreg.h> #include <linux/fdreg.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/time.h>
#include <linux/ptrace.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/tqueue.h> #include <linux/tqueue.h>
#include <linux/resource.h> #include <linux/resource.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
......
...@@ -8,14 +8,10 @@ ...@@ -8,14 +8,10 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -333,10 +329,10 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig); ...@@ -333,10 +329,10 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
if (nr_queued_signals < max_queued_signals) { if (nr_queued_signals < max_queued_signals) {
q = (struct signal_queue *) q = (struct signal_queue *)
kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL); kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL);
nr_queued_signals++;
} }
if (q) { if (q) {
nr_queued_signals++;
q->next = NULL; q->next = NULL;
*t->sigqueue_tail = q; *t->sigqueue_tail = q;
t->sigqueue_tail = &q->next; t->sigqueue_tail = &q->next;
......
...@@ -8,17 +8,13 @@ ...@@ -8,17 +8,13 @@
* bottom_half handler need not be re-entrant. * bottom_half handler need not be re-entrant.
*/ */
#include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/bitops.h> #include <asm/bitops.h>
......
...@@ -6,20 +6,13 @@ ...@@ -6,20 +6,13 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/times.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/param.h>
#include <linux/resource.h> #include <linux/resource.h>
#include <linux/signal.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/tty.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
......
...@@ -22,10 +22,8 @@ ...@@ -22,10 +22,8 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/swapctl.h> #include <linux/swapctl.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/fs.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -20,12 +20,9 @@ ...@@ -20,12 +20,9 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -1567,7 +1567,8 @@ generic_file_write(struct file *file, const char *buf, ...@@ -1567,7 +1567,8 @@ generic_file_write(struct file *file, const char *buf,
bytes = count; bytes = count;
hash = page_hash(inode, pgpos); hash = page_hash(inode, pgpos);
if (!(page = __find_page(inode, pgpos, *hash))) { page = __find_page(inode, pgpos, *hash);
if (!page) {
if (!page_cache) { if (!page_cache) {
page_cache = __get_free_page(GFP_USER); page_cache = __get_free_page(GFP_USER);
if (page_cache) if (page_cache)
...@@ -1580,21 +1581,25 @@ generic_file_write(struct file *file, const char *buf, ...@@ -1580,21 +1581,25 @@ generic_file_write(struct file *file, const char *buf,
page_cache = 0; page_cache = 0;
} }
/* Get exclusive IO access to the page.. */
wait_on_page(page); wait_on_page(page);
set_bit(PG_locked, &page->flags); set_bit(PG_locked, &page->flags);
/*
* Do the real work.. If the writer ends up delaying the write,
* the writer needs to increment the page use counts until he
* is done with the page.
*/
bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes); bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
if (!bytes) {
status = -EFAULT; status = -EFAULT;
if (bytes)
status = inode->i_op->updatepage(file, page, offset, bytes, sync);
/* Mark it unlocked again and drop the page.. */
clear_bit(PG_locked, &page->flags); clear_bit(PG_locked, &page->flags);
wake_up(&page->wait); wake_up(&page->wait);
__free_page(page); __free_page(page);
break;
}
status = inode->i_op->updatepage(file, page, offset, bytes, sync);
__free_page(page);
if (status < 0) if (status < 0)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment